Deploy SQL Server Business Intelligence in
Windows Azure Virtual Machines
SQL Server Technical Article
Writer: Chuck Heinzelman | Senior Program Manager | Microsoft Azure SQLCAT
Contributors: Omer Boker
Technical Reviewers: Craig Guyer, Kay Unkroth, Lara Rubbulke, Alexei Khalyako, Mike Plumley, Yorihito
Tada, Mark Perry, Buck Woody, Xin Jin, Rajinder Singh, Madhan Arumugam Ramakrishnan, Beth Inghram
Revision: 1.03
Published: August 2013
Applies to: SQL Server 2012 SP1 and Windows Azure
Summary: This document describes and walks you through the creation of a multiserver deployment of SQL
Server Business Intelligence features, in a Windows Azure Virtual Machines environment. The document
focuses on the use of Windows PowerShell scripts for each step of the configuration and deployment process.
Page 1 of 86
Copyright
This document is provided “as-is”. Information and views expressed in this document, including URL and other Internet
website references, may change without notice. You bear the risk of using it.
Some examples depicted herein are provided for illustration only and are fictitious. No real association or connection is
intended or should be inferred.
This document does not provide you with any legal rights to any intellectual property in any Microsoft product. You may
copy and use this document for your internal, reference purposes.
© 2013 Microsoft. All rights reserved.
Page 2 of 86
1. Contents
1.
Contents .......................................................................................................................................................................... 3
2.
Introduction .................................................................................................................................................................... 7
3.
What Is Infrastructure as a Service (IaaS)? ..................................................................................................................... 7
4.
Why Infrastructure as a Service (IaaS)? .......................................................................................................................... 7
5.
Recommended Scenarios for BI on IaaS ......................................................................................................................... 7
6.
Document Conventions .................................................................................................................................................. 8
7.
Getting Started with IaaS ................................................................................................................................................ 9
7.1.
Affinity Groups ........................................................................................................................................................ 9
7.2.
Virtual Networks ..................................................................................................................................................... 9
7.2.1.
Subnets............................................................................................................................................................ 9
7.2.2.
DNS ................................................................................................................................................................ 10
7.2.3.
On-Premises Connectivity ............................................................................................................................. 10
7.3.
Storage .................................................................................................................................................................. 10
7.3.1.
Containers ..................................................................................................................................................... 11
7.3.2.
Access Keys ................................................................................................................................................... 11
7.4.
Cloud Service ......................................................................................................................................................... 11
7.4.1.
Deployments ................................................................................................................................................. 11
7.4.2.
Virtual IP Address .......................................................................................................................................... 11
7.5.
Endpoints .............................................................................................................................................................. 12
7.6.
Virtual Machines ................................................................................................................................................... 12
7.7.
Availability Sets ..................................................................................................................................................... 12
7.8.
Disks ...................................................................................................................................................................... 12
7.9.
Images ................................................................................................................................................................... 12
8.
Prerequisites and Assumptions..................................................................................................................................... 14
9.
Windows Azure PowerShell Commands ....................................................................................................................... 15
10.
Non-Windows Azure PowerShell Commands ........................................................................................................... 17
11.
The Overall Environment .......................................................................................................................................... 17
12.
Overview of the Deployment Steps .......................................................................................................................... 20
13.
Step 1: Configure the Windows Azure Environment ................................................................................................ 21
13.1.
13.1.1.
13.2.
Create the Affinity Group .................................................................................................................................. 21
Validation ...................................................................................................................................................... 21
Network............................................................................................................................................................. 22
13.2.1.
Create the Virtual Network ........................................................................................................................... 22
13.2.2.
Validation ...................................................................................................................................................... 24
Page 3 of 86
13.2.3.
13.3.
Create the Cloud Service ............................................................................................................................... 25
13.3.2.
Validation ...................................................................................................................................................... 25
Storage Account ................................................................................................................................................ 25
13.4.1.
Create the Storage Account .......................................................................................................................... 25
13.4.2.
Validation ...................................................................................................................................................... 26
Step2: Deploy Active Directory Domain Services ..................................................................................................... 27
14.1.
First Domain Controller ..................................................................................................................................... 27
14.1.1.
Provision VM ................................................................................................................................................. 28
14.1.2.
Validation ...................................................................................................................................................... 30
14.1.3.
Format Disks.................................................................................................................................................. 31
14.1.4.
Create Domain .............................................................................................................................................. 31
14.1.5.
Create Sites and Subnets .............................................................................................................................. 32
14.1.6.
Remove Forwarder........................................................................................................................................ 34
14.2.
Second Domain Controller ................................................................................................................................ 34
14.2.1.
Provision VM ................................................................................................................................................. 34
14.2.2.
Format Disks.................................................................................................................................................. 38
14.2.3.
Create Domain Controller ............................................................................................................................. 38
14.2.4.
Create Share .................................................................................................................................................. 39
14.3.
14.3.1.
15.
Cloud Service ..................................................................................................................................................... 25
13.3.1.
13.4.
14.
Point-to-Site VPN .......................................................................................................................................... 25
Service User Accounts ....................................................................................................................................... 39
Create Service User Accounts ....................................................................................................................... 40
Step 3: Configure SQL Server Database Servers (SharePoint Back End) ................................................................... 43
15.1.
15.1.1.
First SQL Server Instance................................................................................................................................... 44
Provision VM ................................................................................................................................................. 44
15.2.
Format Disks...................................................................................................................................................... 46
15.3.
Enable Clustering .............................................................................................................................................. 46
15.4.
Install SQL Server .............................................................................................................................................. 46
15.5.
Second SQL Server Instance .............................................................................................................................. 48
16.
Step 4: Configure SQL Server PowerPivot Servers .................................................................................................... 49
16.1.
16.1.1.
Provision VM ................................................................................................................................................. 50
16.1.2.
Install SQL Server .......................................................................................................................................... 52
16.2.
17.
First PowerPivot Server ..................................................................................................................................... 50
Second PowerPivot Server ................................................................................................................................ 53
Step 5: Deploy the first SharePoint Application/Central Administration Server ...................................................... 54
Page 4 of 86
17.1.
17.1.1.
Provision VM ................................................................................................................................................. 54
17.1.2.
Install SharePoint Prerequisites .................................................................................................................... 56
17.1.3.
Install SharePoint .......................................................................................................................................... 57
17.1.4.
Install Add-Ins................................................................................................................................................ 57
17.1.5.
Install Updates .............................................................................................................................................. 58
17.1.6.
Sysprep .......................................................................................................................................................... 58
17.1.7.
Capture Image ............................................................................................................................................... 58
17.2.
First SharePoint Server...................................................................................................................................... 59
17.2.1.
Provision VM ................................................................................................................................................. 59
17.2.2.
Create New Farm .......................................................................................................................................... 61
17.2.3.
Add PowerPivot Solutions ............................................................................................................................. 61
17.2.4.
Install PowerPivot Features .......................................................................................................................... 62
17.2.5.
Configure Service Instance ............................................................................................................................ 62
17.2.6.
Create PowerPivot Service Application......................................................................................................... 62
17.2.7.
Create Default Web Application ................................................................................................................... 62
17.2.8.
Deploy Web Application Solution ................................................................................................................. 63
17.2.9.
Create Site Collection .................................................................................................................................... 63
17.2.10.
Activate PowerPivot Feature .................................................................................................................... 63
17.2.11.
Start the Claims to Windows Token Service ............................................................................................. 63
17.2.12.
Configure Secure Store Service ................................................................................................................. 64
17.2.13.
Configure Alternate Access Mappings ...................................................................................................... 65
17.2.14.
Install Reporting Services .......................................................................................................................... 66
17.2.15.
Install Reporting Services Bits ................................................................................................................... 66
17.2.16.
Enable Reporting Services ......................................................................................................................... 67
17.2.17.
Create Reporting Services Shared Service Application ............................................................................. 68
17.2.18.
Grant Reporting Services permissions ...................................................................................................... 68
17.3.
18.
SharePoint Image .............................................................................................................................................. 54
Section Validation ............................................................................................................................................. 69
Step 6: Configure AlwaysOn Availability Groups ...................................................................................................... 70
18.1.
18.1.1.
18.2.
18.2.1.
18.3.
18.3.1.
Create Cluster.................................................................................................................................................... 70
Validation ...................................................................................................................................................... 71
Enable AlwaysOn Availability Groups ............................................................................................................... 71
Validation ...................................................................................................................................................... 72
Create Availability Group .................................................................................................................................. 72
Validation ...................................................................................................................................................... 73
Page 5 of 86
18.4.
18.4.1.
19.
19.1.1.
19.2.
19.2.1.
19.3.
19.3.1.
19.4.
19.4.1.
19.5.
Provision VM ..................................................................................................................................................... 75
Validation ...................................................................................................................................................... 77
Join SharePoint Farm ........................................................................................................................................ 77
Validation ...................................................................................................................................................... 77
Import Certificate .............................................................................................................................................. 78
Validation ...................................................................................................................................................... 78
Deploy PowerPivot Solutions ............................................................................................................................ 78
Validation ...................................................................................................................................................... 79
Configure Second SharePoint Web Front End .................................................................................................. 79
Step 8: Deploy Additional SharePoint Application/Central Administration Servers ................................................ 80
20.1.
20.1.1.
20.2.
20.2.1.
20.3.
20.3.1.
20.4.
20.4.1.
20.5.
20.5.1.
20.6.
20.6.1.
20.7.
20.7.1.
21.
Validation ...................................................................................................................................................... 74
Step 7: Deploy SharePoint Web Front End Servers .................................................................................................. 75
19.1.
20.
Enable High Availability in SharePoint .............................................................................................................. 74
Provision VM ..................................................................................................................................................... 80
Validation ...................................................................................................................................................... 81
Join SharePoint Farm ........................................................................................................................................ 82
Validation ...................................................................................................................................................... 82
Configure Local Service Instances ..................................................................................................................... 82
Validation ...................................................................................................................................................... 82
Start the SharePoint Services ............................................................................................................................ 83
Validation ...................................................................................................................................................... 83
Deploy PowerPivot Solutions ............................................................................................................................ 83
Validation ...................................................................................................................................................... 83
Install Reporting Services Bits ........................................................................................................................... 84
Validation ...................................................................................................................................................... 84
Enable Reporting Services ................................................................................................................................. 84
Validation ...................................................................................................................................................... 85
Conclusion ................................................................................................................................................................. 86
21.1.
For more information: ...................................................................................................................................... 86
21.2.
Feedback ........................................................................................................................................................... 86
Page 6 of 86
2. Introduction
We’ve been getting more and more requests for guidance on running Business Intelligence (BI) workloads in
Windows Azure Virtual Machines. This paper is a joint effort between the Microsoft SQL Server BI portion of the
Windows Azure Customer Advisory Team and Microsoft's Israel Development Center. The deployment guidance in
this document is based on customer experiences, customer feedback, and user research.
The environment outlined in this document works as a stand-alone environment that does not need to connect to
an on-premises Active Directory domain. It emphasizes BI deployment techniques for Windows Azure Virtual
Machines without going too deeply into individual BI technologies. The paper assumes that you already understand
how to build BI environments in general and you now want to deploy a Microsoft SharePoint based BI environment
in Windows Azure Virtual Machines. This document should serve as a starting point to build such a Windows Azurebased BI environment.
Although this paper describes the use of Windows PowerShell to build the environment, most of these tasks can also
be accomplished through other tools, including the Windows Azure Management Portal, SQL Server Management
Studio, and SharePoint Central Administration. The Windows PowerShell approach does not require the use of
multiple tools and can easily be automated and repeated as needed.
3. What Is Infrastructure as a Service (IaaS)?
IaaS is any environment that enables you to host virtual machines (VMs) without having to build and maintain the
hosting infrastructure yourself. Many corporate IT departments take advantage of virtualization environments to
run their workloads. IaaS eliminates the need to install or maintain host servers, enabling you to focus on your VMs
rather than the infrastructure. In Windows Azure, IaaS is provided through the Windows Azure Virtual Machines
service.
4. Why Infrastructure as a Service (IaaS)?
There are several reasons to run BI workloads on IaaS. Some reasons are related to the general benefits of an IaaS
environment. Other reasons are derived from the combination of IaaS advantages with the characteristics of BI
solutions:




Seamless migration to the cloud. IaaS is the most accessible alternative for migrating BI workloads to the cloud,
because IaaS is very similar to existing on-premises architectures.
No physical infrastructure maintenance. Windows Azure takes care of physical infrastructure deployment and
maintenance for you.
IaaS solutions are flexible. Additional VMs can be created from predefined Windows Azure gallery images or
from custom images. You can deploy additional servers to increase capacity dynamically.
Reduced total cost of ownership (TCO). By accruing costs only for consumed resources, required software SKUs,
and actual resource usage time, IaaS can help to lower TCO. This is especially significant for short-lived projects,
such as demos or proof-of-concept (POC) deployments.
5. Recommended Scenarios for BI on IaaS
IaaS is a good choice for the following scenarios:

Demonstrations – IaaS is a convenient option when you need to demonstrate the new Microsoft BI stack.
No hardware is required, and the deployed solution is available from everywhere. Also, cost is associated
only with the time during which the solution is deployed.

Proof of concept (POC) – IaaS can be used for creating a POC of a BI solution. Running the POC on IaaS
enables trial and error of various architectures while avoiding the high costs associated with buying
Page 7 of 86
hardware. After the BI solution architecture is clear, it can be decided which hardware to buy, or even
continue using IaaS for the production solution. Also, the Windows Azure gallery provides some building
blocks that can save some work in comparison to the on-premises alternative, for example VM images that
contain Operating Systems and so on.

Development/Test/Lab/Training – Development and test environments commonly require an iterative
build-and-try workflow. Training environments frequently require several machines configured in a specific
way for several days, and lab environments can be used for various explorations and scenario testing. For all
these cases, using IaaS is convenient because it provides maximum flexibility—different environments can
be created quickly, and IaaS is easy to scale as needed. Also, as in previous scenarios, cost is minimized to
the actual required resources.
6. Document Conventions
This section describes documentation conventions used in this paper.
Each implementation section starts with a description of the desired end result of that section. If you feel
comfortable implementing the particular section without using the sample scripts included in the document, feel
free to skip the scripted guidance and implement that section on your own.
Important: The implementation sections are progressively dependent on each other; later sections build on
previous sections. You cannot complete sections later in the document if the previous sections have not been
completed by either the scripts provided or manually by you.
Each implementation section concludes with steps and recommendations for how to verify that the steps for that
section completed successfully. You should verify the results of each section before you proceed to the next section.

Scripting Conventions – This document makes wide use of Windows PowerShell script fragments. If the
fragment contains a single command, the text leading up to it provides information on what the script does. If
the fragment contains several commands, the text leading up to it provides information on what the fragment
as a whole does, and comments (Windows PowerShell comments start with #) embedded in the fragment
describe what is happening in more detail.
Page 8 of 86
7. Getting Started with IaaS
This section goes over the topics and terminology specific to Windows Azure. The content in the section is not
specific to BI, but if you are new to Windows Azure, it helps you understand the overall Windows Azure IaaS
environment. If you are comfortable with these topics already, feel free to skip this section and move on to the
architectural guidance.
Note that this information is believed to be accurate at the time of the paper’s publication. The Windows Azure
environment is a live service that receives updates and improvements. For the most up-to-date information about
Windows Azure, see the following:


Windows Azure – http://www.windowsazure.com
Virtual Machines – http://www.windowsazure.com/en-us/documentation/services/virtualmachines/?fb=en-us
7.1. Affinity Groups
In Windows Azure, an affinity group is a logical grouping of resources defined by the user. When storage and
virtual machines are grouped into affinity groups, Windows Azure does all it can to locate these resources
physically close together in the data center, which helps minimize latency. It is important to locate your virtual
machines and the storage close together physically, because the virtual hard disks (VHDs) used by the virtual
machines are stored as blobs in Windows Azure storage.
7.2. Virtual Networks
In Windows Azure, you can define one or more virtual networks within your subscription. A virtual network
is private to you and the services that you deploy to it—VMs that are not a part of the virtual network cannot see
into the virtual network. You can define a single address space or multiple address spaces within your virtual
network, and you can divide those address spaces up into multiple subnets if you want—the flexibility is yours.
It is worth mentioning at this point that it is important to plan your virtual network carefully before you create
resources. After resources (virtual machines in this case) are deployed to a network, most of the configuration
settings on that network cannot be changed. The only way to change configuration settings after deployment is
to deprovision the resources from the network, make your changes, and then add the resources back to the
network. This is time-consuming, and it requires downtime of your applications and services while the work is
being performed.
All IP addresses within Windows Azure Virtual Machines are assigned through Dynamic Host Configuration
Protocol (DHCP) and remain assigned to the VM until the VM is deallocated. It is important that you do not
change the IP address in your virtual machines. If you manually change the IP address, you may lose connectivity
to the VM. Let Windows Azure provide the network settings for all of the machines that you deploy. For more
information, see http://msdn.microsoft.com/en-us/library/windowsazure/dn133803.aspx.
7.2.1. Subnets
A virtual network in Windows Azure supports address space divided into multiple subnets. Routing between
the subnets is automatically handled through Windows Azure, so VMs in one subnet on your virtual network
are automatically able to see VMs in other subnets within the same virtual network. You can add more subnets
to a virtual network after machines are deployed, but you cannot change the settings of existing subnets
without removing all of the deployed resources.
Windows Azure uses some of the addresses in each subnet defined for its own internal purposes. Currently
Windows Azure consumes three addresses from every subnet defined (which is why a /29 subnet is the
smallest that you can define). When you plan your network, make sure that you take this information into
Page 9 of 86
account. You might need to use a larger subnet than you think to accommodate for the addresses that
Windows Azure consumes.
Avoid making assumptions about IP address assignments. It is common for administrators to make the
assumption that the first IP address that they receive in a subnet will be the fourth possible IP address.
For example, for a 10.10.10.0/29 subnet, you might assume that the first IP address handed out is
10.10.10.4. Although that assumption is currently correct, the pattern of IP address assignment can
change at any time without warning. The best bet here is to refrain from making assumptions about
the IP address that your VM will receive.
7.2.2. DNS
Windows Azure provides a Domain Name System (DNS) server that allows you to access the Internet from your
virtual machines. You can also provide your own DNS servers on your virtual network to handle name
resolution within your own network. In the example deployment that we build in this paper, two DNS servers
are defined, and they provide name resolution within the virtual network.
You can define the DNS servers in two places, at the virtual network level and at the Cloud Service level. DNS
settings that are defined at the Cloud Service level apply to every machine deployed into that Cloud Service,
regardless of what the virtual network-level settings are. DNS settings that are defined at the virtual network
level apply to every machine deployed to that network, unless that machine is part of a Cloud Service that has
custom DNS settings.
7.2.3. On-Premises Connectivity
Windows Azure Virtual Networks can be set up for on-premises connectivity in two different ways —point-tosite and site-to-site. Each method has its own purpose, and both can be used in the same virtual network.
Point-to-Site On-Premises Connectivity
Point-to-site connectivity is essentially a virtual private network (VPN) connection into your virtual
network. Your machine gets an IP address on the virtual network, and you can then communicate with
the machines via IP address or via names resolved by a DNS server, if you have configured one. This
best way to think about point-to-site connectivity is like a corporate VPN. When you are off-site, you
can use VPN software provided by your employer to connect to network resources at the office. This is
the same basic technology that corporate VPNs use. The communication channel between your
machine and the virtual network in Windows Azure is handled through certificates that you create and
load rather than user names and passwords.
Site-to-Site On-Premises Connectivity
Site-to-site connectivity is different from point-to-site connectivity. Site-to-site connectivity is meant to
be a permanent tunnel between your corporate environment and your virtual network in Windows
Azure. If you set up site-to-site connectivity, your cloud-based virtual machines can actually be a part of
your corporate domain structure.
7.3. Storage
Windows Azure Virtual Machines make extensive use of .vhd files, similar to what is used in on-premises
Windows Server Hyper-V environment. You can have multiple distinct storage accounts within a single Windows
Azure subscription, and you can spread files from VMs across multiple storage accounts. The .vhd files used by
Windows Azure Virtual Machines are stored in Windows Azure Blob Storage as page blobs. This is an important
distinction because there are two types of blobs in blob storage: page blobs and block blobs. For .vhd files, you
use page blobs.
Page 10 of 86
If you have existing machines that you want to host and run in Windows Azure Virtual Machines, you can
upload the .vhd files to Windows Azure Blob Storage and create a virtual machine based on them. You can also
upload a .vhd that includes a sysprepped virtual machine that can be used as an image to create multiple
virtual machines. You can also create new .vhd by creating a new virtual machine ‘Disk’ in the management
portal (or Windows PowerShell Add-AzureDatadisk).
7.3.1. Containers
Rather than folders, blob storage uses containers to store blobs. When you are working with virtual
machines, a “vhds” container is automatically created for you. Containers have three different levels of
security: Private, Public Container, and Public Blob. The “vhds” container that is created when you
create virtual machines is created as Private.
When you work with virtual machines, you can use whatever container structure works best for you. All
you need to do when creating a virtual machine is provide the full path to the .vhd file.
The following diagram illustrates the Windows Azure objects that are part of the storage environment:
7.3.2. Access Keys
Windows Azure storage accounts can be accessed from various third-party tools (as well as the published API).
This access is commonly done by using one of the access keys on the storage account. Each storage account has
two access keys: a Primary Access Key and a Secondary Access Key. Both keys provide the same level of access.
There are two keys so that if you want to perform periodic key maintenance you can change one of them while
still accessing your storage through the other.
7.4. Cloud Service
The cloud service is the heart of your cloud-based deployment. It provides a public face to your infrastructure if
you want it to have one. Your level of exposure to the Internet is controlled by how much you open your cloud service.
7.4.1. Deployments
Cloud services can have multiple deployments. For the purposes of working with Windows Azure Virtual Machines, the
examples in this paper use production deployments.
7.4.2. Virtual IP Address
Each cloud service gets a single public-facing IP address. Along with that, it gets a public DNS entry. If you name your
cloud service “BIPaper”, its public DNS entry will be “BIPaper.cloudapp.net”. This IP address (and public DNS entry) is
how you connect to the resources running as part of the cloud service.
Page 11 of 86
7.5. Endpoints
For each virtual machine that you deploy, you can define one or more public endpoints. An endpoint is a public/private
port pairing that acts as a bridge between the public virtual IP address and the private virtual machine IP address. For
example, if you want inbound (public) traffic on port 53186 of the virtual IP address routed to port 3389 on a given
virtual machine, you can set up an endpoint on that virtual machine with a public port of 53186 and a private port of
3389.
A public port can only be used once per cloud service—unless you set the endpoints up as load-balanced endpoints. You
can share a single public endpoint across multiple virtual machines by using the built-in load balancer in Windows Azure.
Many people may want to use remote desktop to connect to their Windows Azure-based virtual machines. The easiest
way to do this is through a point-to-site VPN, but you can still do it without a VPN. Set up an endpoint on each virtual
machine that you want to access with a private port of 3389 (the standard port for RDP) and an obfuscated public port.
The obfuscation of the public port provides two benefits: 1) multiple machines in the same cloud service can use the
same private port without load balancing, and 2) port 3389 is a well-known port and using it as your public RDP port can
open your infrastructure up for potential attacks.
7.6. Virtual Machines
Virtual machines are at the core of what we are doing in this paper. In many ways, the machines that you host in
Windows Azure are no different than the machines that you host in Hyper-V on-premises. There are a few things, such
as snapshots, that you are unable to do with Windows Azure Virtual Machines, and you do not have direct access to the
Hyper-V management tools. All management of virtual machines needs to be done either through the Windows Azure
Management Portal (https://manage.windowsazure.com/) or through the exposed APIs.
7.7. Availability Sets
Availability sets are logical groupings of virtual machines. Periodically, the host operating systems that run underneath
your virtual machines need to be updated. When these updates happen, any virtual machine running on that host is
taken offline. To get the promised service-level agreement (SLA) for Windows Azure Virtual Machines, you need to have
at least two machines running in a given role (two domain controllers, for example). Placing those machines in the same
availability set tells Windows Azure that it should make sure that one machine always remains up while host
maintenance is being performed.
7.8. Disks
To present a .vhd stored in blob storage to a virtual machine, verify that the .vhd has a Windows Azure Disk defined.
Disks can be marked as data disks, bootable disks (which contain an operating system image), or images (which contain a
sysprepped image that can be used for creating other virtual machines). In this paper, all three disk types are used.
7.9. Images
Images are templates in the world of Windows Azure Virtual Machines. There are prebuilt gallery images for a
variety of technologies, including Windows Server and SQL Server. If you have a situation where you need to
add machines to your deployments quickly (such as scaling out a SharePoint environment), you can create your
own custom images with your software preinstalled. These images can then be used as a template for creating
additional machines. One word of caution—make sure that the software you install on the image supports
being sysprepped.
The procedures in this document use a base Windows Server image from the Windows Azure Virtual
Machines gallery. The procedures do not use gallery images that contain SQL Server. We made this choice for
the following reasons:
Page 12 of 86

The gallery images have most of SQL Server installed and running. Many of these features are not needed
for the BI scenarios covered in this document. To simplify the installation and configuration procedure, the
scripts install only the SQL Server features that are needed for the BI scenarios.

Leveraging the gallery images that have SQL Server already installed does not allow you to make use of
your existing licenses. The procedures in this document assume you supply the installation files and
necessary licenses for SQL Server and SharePoint. For more information, see the prerequisites and
assumptions section of this document.
Page 13 of 86
8. Prerequisites and Assumptions
We made several assumptions about our readers and your environments while we were writing this paper:



Installation Bits – For the purpose of this paper we used the Windows Server 2012 gallery images. These images
do not have any additional software installed on them. You will need to provide the installation media for SQL
Server 2012 with SP1 (Enterprise or Business Intelligence edition), SharePoint Server 2013 (Enterprise) and any
service packs and cumulative updates you want to apply. The paper was written using the following software:
 SQL Server 2012 Enterprise Core edition
 SQL Server 2012 ervice pack (SP) 1 and cumulative update (CU) 4
 SharePoint Server 2013 Enterprise edition
 SharePoint Server 2013 March 2013 CU
 SharePoint Server 2013 April 2013 CU
Licensing – Through the use of the Windows Server 2012 gallery images, the Windows licensing is covered on a
pay-by-the-hour basis. Any licensing for the SQL Server and SharePoint components are the responsibility of the
person doing the installation. For more information about Windows Azure pricing and licensing, see
http://www.windowsazure.com/en-us/pricing/details/virtual-machines/.
Windows Azure Subscription – You will need access to a Windows Azure subscription with a sufficient number
of cores allocated. The default is 20 cores per subscription. To build the entire lab outlined in this document, you
need 66 cores at the recommended machine sizes. To increase the core quota, contact
http://www.windowsazure.com/en-us/support/options/.
Important: After you are finished developing and testing the scripts, verify that the Windows Azure resources
are in the desired state so you are not charged for resources you do not need. For example, if you leave Windows
Azure Virtual Machines running, you are charged compute hours. If you do not want to delete virtual machines and
you do not want to incur charges while the virtual machine is unused, shut down the virtual machine(s) in the
Windows Azure Management Portal. For more information about the cost of Windows Azure compute charges, see
http://www.windowsazure.com/en-us/pricing/calculator/.




Management Certificate – To use the scripts included in this paper, you need to create a management
certificate and upload it into the Windows Azure Management Portal. For more information about how to do
this, see Cloud Spelunking, Managing Azure form your Desktop via PowerShell (the Setup)
(http://blogs.msdn.com/b/sql_shep/archive/2013/03/29/cloud-spelunking-managing-azure-form-your-desktopvia-powershell.aspx).
VPN Certificate – If you plan to use the point-to-site VPN functionality to access your virtual machines, you need
to create your root and client certificates. For more information about how to do this, see Configure a Point-toSite VPN in the Management Portal (http://msdn.microsoft.com/en-us/library/windowsazure/dn133792.aspx).
Windows Azure PowerShell Cmdlets – If you intend to use the scripts included in this paper, you need to
download and install the Windows Azure PowerShell cmdlets (the scripts in this document were created using
the June 2013 cmdlets). For more information about how to download Windows Azure PowerShell, see
Downloads (http://www.windowsazure.com/en-us/downloads/#cmd-line-tools).
Windows PowerShell Scripting – It is our assumption that people using this document will have a basic working
knowledge of Windows PowerShell, including the definition and use of variables and scripts. For more
Page 14 of 86


information about using Windows PowerShell, see Getting Started with Windows PowerShell
(http://technet.microsoft.com/en-us/library/hh857337.aspx).
Windows PowerShell Integrated Scripting Environment (ISE) – We recommend that you use the Windows
PowerShell ISE tool for running the scripts included in this document. The Windows PowerShell ISE is installed by
default on Windows Server 2012.
On-Box vs. Off-Box Scripts – In this paper, the terms on-box and off-box are used when in discussions of
Windows PowerShell scripts. On-box scripts are Windows PowerShell scripts that should be run while you are
logged into the specified virtual machine. They do not require any of the Windows Azure settings, but they do
require certain variables to be created and populated. Off-box scripts are Windows PowerShell scripts that
should be run from a local workstation. They require the Windows Azure settings and variables.
9. Windows Azure PowerShell Commands
This section describes script related document conventions and best practices regarding the Windows Azure-related
PowerShell commands contained in this document.
Run the following command before you run any Windows Azure PowerShell commands.
Import-Module "C:\Program Files (x86)\Microsoft SDKs\Windows
Azure\PowerShell\Azure\Azure.psd1"
This command ensures that the Windows Azure PowerShell cmdlets are loaded. Make sure that the path is
correct for where your Azure.psd1 file is located.
The following standard variable names are used throughout the document.
Variable name
$subscriptionName
$subscriptionID
$thumbPrint
$affinityGroupLocation
$affinityGroupName
$affinityGroupDescription
$affinityGroupLabel
$virtualNetworkName
$cloudServiceName
$cloudServiceDescription
$cloudServiceLabel
$storageAccountName
$storageAccountLabel
$domainName
$domainNameFQ
Purpose/source
The name of your Windows Azure subscription
The unique identifier for your Windows Azure subscription (can be found
in the Settings section of the Windows Azure Management Portal under
Management Certificates)
The thumbprint of the management certificate that you uploaded to the
Windows Azure Management Portal
The Windows Azure data center where you will be deploying your
resources
The name of the affinity group (must be unique in your subscription)
The description for the affinity group
The label for the affinity group
The name for the virtual network (must be unique in your subscription)
The cloud service name you want to use (must be globally unique)
The description for the cloud service
The label for the cloud service
The storage account name you want to use (must be globally unique)
The label for the storage account
The NetBIOS name of the domain being created (BIPaper, for example)
The fully qualified domain name (FQDN) of the domain being created
(BIPaper.local, for example)
We suggest having these variables and the Import-Module command in a script file that you run with each of
the off-box scripts that you run. Here is a sample script block that contains these variables, including default
values for responses that are assumed in the paper.
Page 15 of 86
# Import PowerShell Module...
Import-Module "C:\Program Files (x86)\Microsoft SDKs\Windows Azure\PowerShell\Azure\Azure.psd1"
# Variable Block...
# Subscription Information...
$subscriptionName = ""
$subscriptionID = ""
$thumbPrint = ""
# Affinity Group Information...
$affinityGroupLocation = "" # To see possible locations, run the command: Get-AzureLocation | FT
Name, AvailableServices
$affinityGroupName = "BIPaper-AffinityGroup"
$affinityGroupDescription = "Affinity Group used for the BI in IaaS Paper" # Maximum of 1024
Characters...
$affinityGroupLabel = "BI in IaaS Paper Affinity Group" # Maximum of 100 Characters...
# Virtual Network Information...
$virtualNetworkName = "BIPaper-Network"
# Cloud Service Information...
$cloudServiceName = ""
$cloudServiceDescription = "Cloud Service used for the BI in IaaS Paper"
$cloudServiceLabel = "BI in IaaS Paper Cloud Service"
# Storage Account Information...
$storageAccountName = "" # Must be globally unique and all lowercase...
$storageAccountLabel = ""
# Domain Information...
$domainName = "BIPaper"
$domainNameFQ = "BIPaper.local"
In addition, you should set and select your subscription with each command, especially if your account is associated with
more than one subscription. There are two different methods for setting your subscription, one for a subscription that
contains a storage account and one for a subscription that does not have a storage account. Each script listed includes
information about which method to use.

Without storage account:
$certificate = Get-Item cert:\currentuser\my\$thumbPrint
Set-AzureSubscription `
-SubscriptionName $subscriptionName `
-SubscriptionId $subscriptionID `
-Certificate $certificate
Select-AzureSubscription `
-SubscriptionName $subscriptionName

With storage account:
$certificate = Get-Item cert:\currentuser\my\$thumbPrint
Set-AzureSubscription `
-SubscriptionName $subscriptionName `
-SubscriptionId $subscriptionID `
-Certificate $certificate `
-CurrentStorageAccount $storageAccountName
Select-AzureSubscription `
-SubscriptionName $subscriptionName
Page 16 of 86
10.
Non-Windows Azure PowerShell Commands
The following is the list of standard variables that this paper uses for Windows PowerShell commands. The variables
are not used for Windows Azure PowerShell.
Variable name
$domainNameFQ
$domainName
$dbServer
$dbServer2
$farmServiceAccount
$reportingServiceAccount
$cloudServiceName
$clusterName
$quorumServerName
Purpose/source
The fully qualified domain name (FQDN) that you want to use
(BIPaper.local, for example)
The NetBIOS name for the domain (BIPaper, for example)
The name of the primary database server (BIPaper-DB1, for example)
The name of the secondary database server (BIPaper-DB2, for example)
The name of the service account to use for running the SharePoint farm
(SP_Farm, for example)
The name of the service account to use for running SQL Server
Reporting Services (SQL_Reporting, for example)
The name used for the Windows Azure cloud service (BIPaper, for
example)
The name used for the Windows Failover Cluster required by AlwaysOn
Availability Groups (BIPaper-DB, for example)
The name of the server that hosts the Quorum share (BIPaper-DC2, for
example)
As with the off-box variables discussed earlier, we suggest including all of these variables and their values in a script file
that can be run with each of the on-box scripts that you run. Here is a sample script block containing these variables,
including default values for responses that are assumed in the paper.
# Variable Block...
$domainNameFQ = "BIPaper.local"
$domainName = "BIPaper"
$dbServer = "BIPaper-DB1"
$dbServer2 = "BIPaper-DB2"
$farmServiceAccount = "SP_Farm"
$reportingServiceAccount = "SQL_Reporting"
$cloudServiceName = "BIPaper"
$clusterName = "BIPaper-DB"
$quorumServerName = "BIPaper-DC2"
11.
The Overall Environment
In this document, we are going to build a SharePoint-based BI environment that has high availability (HA) designed
in at each level. The environment is illustrated in the following diagram. We start with the Windows Azure
infrastructure, and then we proceed through building:

Domain controllers (BiPaper-DC1, Bipaper-DC2)

Database servers (Bipaper-DB1, Bipaper-DB2)

PowerPivot servers (BiPaper-PP1, Bipaper-PP2)

SharePoint farm server (BiPaper-App1).
After the system is up and operational, we scale it out by adding:

Two Web Front End (WFE) servers (BiPaper-WFE1, BiPaper-WFE2) behind a Windows Azure load
balancer.
Page 17 of 86

A second SharePoint application-tier server (BiPaper-App2) for HA
Page 18 of 86
The following diagram shows the complete architecture used in this paper, including IP addresses, subnets, and computer names.
DBNet
(172.16.2.0/24)
BIPaper-DB1
BIPaper-DB2
DBAffinityGroup
ADNet
(172.16.1.0/29)
BIPaper-PP1
BIPaper-PP2
PPAffinityGroup
BIPaper-DC1
BIPaper-DC2
AppAffinityGroup
https Load Balancer
AppAffinityGroup
BIPaper-App1
BIPaper-App2
AppNet
(172.16.3.0/24)
WebAffinityGroup
BIPaper-WFE1
BIPaper.cloudapp.net
BIPaper-WFE2
WebNet
(172.16.4.0/24)
https://bipaper.cloudapp.net
Client
Page 19 of 86
12.
Overview of the Deployment Steps
The following table lists the high-level steps to deploy a full-featured BI environment in IaaS. The steps walk you through
a deployment that is intended to illustrate several useful technologies and how they work together in a highly available
design. You may decide in your environment to not include some technologies.
#
1
Step
Configure the Windows Azure
Environment
2
Deploy Active Directory Domain
Services (AD DS)
3
Configure SQL Server Database
Servers
Configure PowerPivot Servers
4
5
6
7
8
Deploy the first SharePoint
Application/Central
Administration Server
Configure AlwaysOn Availability
Groups
Deploy SharePoint Web Front
End Servers
Deploy Additional SharePoint
Application/Central
Administration Servers
Description
Configuration of the core elements of the Windows Azure
environment: affinity group, virtual networking, storage, and
cloud service.
Provisioning and configuration of two domain controllers to
support the environment and creation of user accounts for
services.
Provisioning and configuration of two SQL Server database servers
to support highly available storage of the SharePoint databases.
Provisioning and configuration of two (or more) SQL Server
Analysis Services SharePoint mode servers to support loading of
PowerPivot workbooks.
Provisioning and configuration of the first SharePoint App-Tier
server, including Central Administration, Microsoft Excel Services,
Reporting Services, and PowerPivot.
Configuring an availability group, including all of the SharePoint
databases that were created.
Provisioning and configuration of multiple SharePoint Web Front
End servers to support Internet traffic.
Provisioning and configuration of additional SharePoint App-Tier
servers to support scaled-out load balancing.
Page 20 of 86
13.
Step 1: Configure the Windows Azure Environment
The first step of the process is to configure the Windows Azure environment to make it ready for deploying our
virtual machines. If you are comfortable with creating a Windows Azure infrastructure on your own without the
samples, create the following infrastructure objects and skip to the section Step2: Deploy Active Directory Domain
Services. Otherwise, continue reading for the step-by-step instructions.
The following list describes the different elements this paper uses in the Windows Azure environment.
Important: The bold names in the following list are names that are required through the remainder of this
paper. If you use different names, be sure to adjust the other scripts that use these names.




Affinity group – BIPaper-AffinityGroup
The affinity group that we create binds all of the infrastructure assets together. The affinity group lets Windows
Azure know that these different pieces (network, virtual machine, storage, and so on) are working together and
that they should be physically located near each other to reduce latency between the different parts of the
system.
Network:
 Name – BIPaper-Network
 Affinity Group – BIPaper-AffinityGroup
 Point-to-Site Address Space – 172.16.128.0/29 (this is necessary only if you are using point-to-site VPN)
 Address Space – 172.16.0.0/17
 Subnets:
 ADNet – 172.16.1.0/29
 DBNet – 172.16.2.0/24
 AppNet – 172.16.3.0/24
 WebNet – 172.16.4.0/24
 Gateway – 172.16.127.0/29 (this is necessary only if you are using point-to-site VPN)
 If you are configuring point-to-site VPN:
 Create Gateway
 Upload Root Certificate
 Configure VPN Connection
Cloud Service:
 Name – Choose a globally unique name (for this paper, we used bipaper)
 Affinity Group – BIPaper-AffinityGroup
Storage Account:
 Name – Choose a globally unique name (for this paper, we used bipapersp)
 Affinity Group – BIPaper-AffinityGroup
13.1.
Create the Affinity Group
To create the affinity group, run the following Windows Azure PowerShell command (use the variable/subscription block
without the storage account).
New-AzureAffinityGroup `
-Location $affinityGroupLocation `
-Name $affinityGroupName `
-Description $affinityGroupDescription `
-Label $affinityGroupLabel
13.1.1. Validation
There are two ways to verify that the affinity group has been created:
Page 21 of 86

Portal – In the Windows Azure Management Portal (https://manage.windowsazure.com), click Settings and then
click Affinity Groups to verify that it exists (you might need to refresh the page).

Windows PowerShell – Run the following Windows PowerShell command (include the same variable script
block used to run the command listed earlier). It should return the value True.
((Get-AzureAffinityGroup | where {$_.Name -eq $affinityGroupName}) -ne $NULL)
13.2.
Network
The network that we will be creating provides subnets and address spaces for each virtual machine that we deploy. We
have divided our network up as follows:



Address Space – 172.16.0.0/17. This is the total possible pool of IP addresses that can be assigned in our virtual
network. There are 32,763 usable addresses.
Point-to-Site Address Space – 172.16.128.0/29. This is the address space allocated to the machines that connect
via the point-to-site VPN feature. There are six usable addresses.
Subnets: The subnets defined here are strictly for logical grouping of machines.
 ADNet – 172.16.1.0/29. This is the address space allocated to our Active Directory servers. There are
three usable addresses.
 DBNet – 172.16.2.0/24. This is the address space allocated to our database servers, There are 251 usable
addresses.
 AppNet – 172.16.3.0/24. This is the address space allocated to our app-tier servers. There are 251 usable
addresses.
 WebNet – 172.16.4.0/24. This is the address space allocated to our web servers. There are 251 usable
addresses.
 Gateway – 172.16.127.0/29. This is a subnet used by the internal gateway. There are three usable
addresses.
13.2.1. Create the Virtual Network
The way that the network is created depends on whether you have existing virtual networks defined. If your subscription
has existing networks defined, you can merge the new network configuration into the existing configuration. If your
subscription does not have existing networks defined, you can create the entire network from scratch. The script in step
3 automatically detects which scenario you have and acts accordingly.
Here are the steps for network creation:
Page 22 of 86
1) Save the following XML block into a file named “C:\Temp\NetworkDef.xml”.
<VirtualNetworkSite name="placeholder-network" AffinityGroup="placeholder-affinitygroup">
<AddressSpace>
<AddressPrefix>172.16.0.0/17</AddressPrefix>
</AddressSpace>
<Subnets>
<Subnet name="ADNet">
<AddressPrefix>172.16.1.0/29</AddressPrefix>
</Subnet>
<Subnet name="DBNet">
<AddressPrefix>172.16.2.0/24</AddressPrefix>
</Subnet>
<Subnet name="AppNet">
<AddressPrefix>172.16.3.0/24</AddressPrefix>
</Subnet>
<Subnet name="WebNet">
<AddressPrefix>172.16.4.0/24</AddressPrefix>
</Subnet>
<Subnet name="GatewaySubnet">
<AddressPrefix>172.16.127.0/29</AddressPrefix>
</Subnet>
</Subnets>
<Gateway>
<VPNClientAddressPool>
<AddressPrefix>172.16.128.0/29</AddressPrefix>
</VPNClientAddressPool>
<ConnectionsToLocalNetwork />
</Gateway>
</VirtualNetworkSite>
2) Save the following XML block into a file named “C:\Temp\NetworkDef-Full.xml”.
<NetworkConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration">
<VirtualNetworkConfiguration>
<Dns />
<VirtualNetworkSites>
<VirtualNetworkSite name="placeholder-network" AffinityGroup="placeholder-affinitygroup">
<AddressSpace>
<AddressPrefix>172.16.0.0/17</AddressPrefix>
</AddressSpace>
<Subnets>
<Subnet name="ADNet">
<AddressPrefix>172.16.1.0/29</AddressPrefix>
</Subnet>
<Subnet name="DBNet">
<AddressPrefix>172.16.2.0/24</AddressPrefix>
</Subnet>
<Subnet name="AppNet">
<AddressPrefix>172.16.3.0/24</AddressPrefix>
</Subnet>
<Subnet name="WebNet">
<AddressPrefix>172.16.4.0/24</AddressPrefix>
</Subnet>
<Subnet name="GatewaySubnet">
<AddressPrefix>172.16.127.0/29</AddressPrefix>
</Subnet>
</Subnets>
<Gateway>
<VPNClientAddressPool>
<AddressPrefix>172.16.128.0/29</AddressPrefix>
</VPNClientAddressPool>
<ConnectionsToLocalNetwork />
</Gateway>
</VirtualNetworkSite>
</VirtualNetworkSites>
</VirtualNetworkConfiguration>
</NetworkConfiguration>
3) Run the following Windows Azure PowerShell (use the variable/subscription block without the storage account).
# Get a temporary path for the network config...
$networkTempPath = [IO.Path]::GetTempFileName()
Page 23 of 86
# Get the current network configuration...
Get-AzureVNetConfig -ExportToFile $networkTempPath
# Determine whether we got the network configuration...
if ((Test-Path $networkTempPath) -eq $false)
{
# Didn't get a config file...
# Load the full network config...
[string]$networkConfig = Get-Content ("C:\Temp\NetworkDef-Full.xml")
# Replace the placeholder name and affinity group with the variable values...
$networkConfig = $networkConfig.Replace("placeholder-network",
$virtualNetworkName).Replace("placeholder-affinitygroup", $affinityGroupName)
# Save the network configuration...
$networkConfig.Save($networkTempPath)
}
else
{
# Got a config file...
# Load the config file...
[xml]$networkConfig = Get-Content $networkTempPath
# Check for VirtualNetworkSites node...
if
($networkConfig.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("VirtualNetwo
rkSites") -eq $NULL)
{
# VirtualNetworkSites node not found...create one...
$virtualNetworkNamespace =
"http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration"
$vncNode = $networkConfig.CreateNode("element", "VirtualNetworkSites",
$virtualNetworkNamespace)
$networkConfig.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").AppendChild($vncNod
e)
}
# Merge in the predefined configuration...
# Load the network config fragment...
[string]$networkConfigNode = Get-Content ("C:\Temp\NetworkDef.xml")
# Replace the placeholder name and affinity group with the variable values...
$networkConfigNode = $networkConfigNode.Replace("placeholder-network",
$virtualNetworkName).Replace("placeholder-affinitygroup", $affinityGroupName)
# Merge the fragment into the full file...
$networkConfig.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("VirtualNetwor
kSites").InnerXML += $networkConfigNode
# Save the network configuration...
$networkConfig.Save($networkTempPath)
}
# Upload the network configuration...
Set-AzureVNetConfig -ConfigurationPath $networkTempPath
# Clean up the temporary file...
Remove-Item -Path $networkTempPath
13.2.2. Validation
There are two ways to verify that the network has been created:

Portal – In the Windows Azure Management Portal, click Networks and verify that the network exists (you might
need to refresh the page); also review the configuration to make sure it looks like what was defined earlier in
the paper.

Windows PowerShell – Run the following Windows PowerShell command (include the same variable script
block used to run the command listed earlier). It should return the value True.
Page 24 of 86
((Get-AzureVnetSite | Where {$_.Name -eq $virtualNetworkName}) -ne $NULL)
13.2.3. Point-to-Site VPN
If you want to use the point-to-site VPN capabilities (as of this writing, the feature is in a preview state), complete the
configuration as outlined here: http://msdn.microsoft.com/enus/library/windowsazure/dn133792.aspx#bkmk_CreatingVNET (starting with the “Create a dynamic routing gateway”
heading; everything prior to that has already been completed through the network configuration). If you chose not to
not the point-to-site VPN functionality, you will need to remove the “-NoRDPEndpoint” switch from the “AddAzureProvisioningConfig” commands for your virtual machines. This change allows Windows Azure to create a RDP
endpoint that you can use to connect to the machine.
13.3.
Cloud Service
The cloud service provides a container for all of the virtual machines to live in, as well as a public IP and DNS entry for us
to use for access. It is possible to have multiple cloud services sharing a single virtual network, but for this paper we
have only one.
13.3.1. Create the Cloud Service
To create the cloud service, run the following Windows Azure PowerShell command (use the variable/subscription block
without the storage account).
New-AzureService `
-AffinityGroup $affinityGroupName `
-ServiceName $cloudServiceName `
-Description $cloudServiceDescription `
-Label $cloudServiceLabel
13.3.2. Validation
There are two ways to verify that the cloud service was created:

Portal – In the Windows Azure Management Portal, click Cloud Services and then verify that the cloud service
exists (you might need to refresh the page).

PowerShell – Run the following Windows PowerShell command (include the same variable script block used to
run the command listed earlier). It should return the value True.
((Get-AzureService | where {$_.ServiceName -eq $cloudServiceName}) -ne $NULL)
13.4.
Storage Account
For the purposes of this paper, we will put all of our resources into a single storage account. This may not be the optimal
situation for a high-throughput production system (especially if you have database servers that perform a large number
of storage transactions). There is one reason, however, to put multiple virtual machines into a single storage account—
custom-built images (which we discuss later in the paper).
13.4.1. Create the Storage Account
To create the storage account, run the following Windows Azure PowerShell command (use the variable/subscription
block without the storage account defined).
New-AzureStorageAccount `
-StorageAccountName $storageAccountName `
-Label $storageAccountLabel `
-AffinityGroup $affinityGroupName
Page 25 of 86
13.4.2. Validation
There are two ways to verify that the storage account was created:

Portal – In the Windows Azure Management Portal, click Storage and then verify that the storage account exists
(you might need to refresh the page).

Windows PowerShell – Run the following Windows PowerShell command.
((Get-AzureStorageAccount | where {$_.StorageAccountName -eq $storageAccountName}) -ne $NULL)
At this point, your Windows Azure environment should be configured and ready for us to move on to creating the actual
virtual machines.
To Overview of the deployment steps
Page 26 of 86
14.
Step2: Deploy Active Directory Domain Services
Now that our Windows Azure infrastructure is in place, we need to start building out the virtual machines that will
support the BI scenario. This starts with two domain controllers (BIPaper-DC1 and BIPaper-DC2). We need two domain
controllers for high availability and to meet the Windows Azure SLA (which requires two or more machines in the same
role—in this case the role is domain controller). One of the machines will have a share on it to hold our installation
media for the other servers that we build, and the other machine will have a share that will serve as the quorum share
for the Windows Failover Cluster that we build in a later step. It is a best practice to put your Active Directory databases
on a disk that does not have write caching enabled (the C: drive of your VM will have caching enabled, and you should
not change that setting), so that will be part of our build-out procedure. Another thing that we learned in testing is that
the Windows Azure DNS server automatically gets added to the first domain controller as a forwarder. In the scripts we
remove this automatic configuration.
At the end of this section, you will have an environment that looks like this:


First Domain Controller:
 Server Name – BIPaper-DC1
 Storage Account – <your globally unique name>
 Domain/Forest Name – BIPaper.local
 Domain/Forest Functional Level – Windows Server 2012
 Acting as a DNS Server
 Active Directory Sites and Subnets Created to match the Virtual Network definition
 Attached Disk – 50 GB for Active Directory databases (scripts format as Z)
 Network Subnet – ADNet
 Availability Set – ADAvailabilitySet
 Server added to Windows Azure Virtual Network as a DNS server
Second Domain Controller:
 Server Name – BIPaper-DC2
 Storage Account – <your globally unique name>
 Domain/Forest Name – BIPaper.local
 Domain/Forest Functional Level – Windows Server 2012
 Acting as a DNS Server
 Attached Disk – 50 GB for Active Directory databases (scripts format as Z)
 Network Subnet – ADNet
 Availability Set – ADAvailabilitySet
 Server added to Windows Azure Virtual Network as a DNS server
 Public Share – Quorum
 Change access granted to everyone
If you feel comfortable creating this environment on your own, you can do so and then skip to the “Service User
Accounts” section.
14.1.
First Domain Controller
The first domain controller that we will create provides the foundation for all other machines that we build. It serves as
not only an Active Directory server, but also as an internal DNS server for name resolution between our VMs. As with all
of the virtual machines we will be creating, the first step is a Windows Azure PowerShell command that runs off-box and
creates the machine itself. The remaining steps are Windows PowerShell commands that run while you are logged into
the VM.
Page 27 of 86
14.1.1. Provision VM
This is the only off-box task within the scope of creating the first domain controller. All other scripts are run in a remote
desktop session on the machine. This script consists of the following elements:



Variable Block – This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
VM Creation – This section (starting with the comment “Creating the virtual machine…”) consists of the
following Windows Azure commands:
 New-AzureVMConfig – This command begins the definition of the virtual machine. It sets the name, size,
image, vhd location and label, and availability set.
 Add-AzureProvisioningConfig – This command determines how Windows Azure should provision the VM
defined in the last command. It tells Windows Azure that this will be a Windows machine, that
automatic updates should be disabled (you can turn this back on if you want), that there should not be
endpoints for RDP or Remote Windows PowerShell, and what the administrator user and password
should be.
 Set-AzureSubnet – This command defines what subnet the virtual machine should be deployed into.
 Add-AzureDataDisk – This command attaches an empty disk to the virtual machine when it is created.
The command defines the size and storage location of the disk, as well as the LUN and cache setting.
 New-AzureVM – This command creates the virtual machine that was defined in the earlier commands. In
addition to the information gathered from the earlier commands, it defines the cloud service and virtual
network that should be used. The script loops until creation of the VM is complete and the script writes
a status to the screen every 15 seconds.
DNS Creation – This section (starting with the comment “DNS Variables…”) consists of the following sections:
 DNS Variables – A set of variables used to create a DNS entry in the virtual network.
 Get the Windows Azure Network Configuration File – Loads the current virtual network configuration.
 Check for DNS Node – Checks the network configuration XML for a DNS node and creates one if it does
not exist.
 Check for DnsServers Node – Checks the network configuration XML for a DnsServers node and creates
one if it does not exist.
 Add DNS Server Entry – Adds the newly created domain controller as an available DNS server.
 Add DNS Servers Reference – Checks the network configuration XML for a DnsServersRef node in the
paper’s virtual network and creates one if it does not exist.
 Add DNS Server Reference – Checks the network configuration XML for a DnsServerRef node in the
paper’s virtual network and creates one if it does not exist.
 Save the Network Configuration – Saves the network configuration XML.
 Update the Network Configuration – Uploads the updated network configuration to Windows Azure.
 Clean Up After Yourself – Cleans up the temporary file used for the network configuration.
To create the first domain controller, run the following Windows Azure PowerShell command (use the
variable/subscription block with the storage account defined).
# Get the name for the VM...
$vmName = "BIPaper-DC1"
# Get the admin user name for the VM...
$vmAdminUserName = Read-Host -Prompt "Server Administrator User Name"
# Ask for the password that should be used for the server and convert it to a format usable by the
commands...
$vmAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Server Administrator Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($vmAdminPasswordSecure)
$vmAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
Page 28 of 86
# Get the name of the VM Image to use...
$vmImageName = (Get-AzureVMImage | Where { $_.Category -eq "Microsoft Windows Server Group" -and
$_.Label -like "Windows Server 2012 Datacenter*" } | Sort-Object PublishedDate -Descending | SELECT
ImageName)[0].ImageName
# Set the location for the .vhd files...
$storageAccountContainer = "https://" + $storageAccountName + ".blob.core.windows.net/vhds/"
$vmVHDLocation = $storageAccountContainer + $vmName + ".vhd"
$vmADVHDLocation = $storageAccountContainer + $vmName + "_ADData.vhd"
$vmADVHDName = $vmName + " AD Data"
# Create the virtual machine...
Write-Host "Creating the VM..."
New-AzureVMConfig `
-Name $vmName `
-InstanceSize Small `
-ImageName $vmImageName `
-MediaLocation $vmVHDLocation `
-DiskLabel "OS" `
-AvailabilitySetName "ADAvailabilitySet" |
Add-AzureProvisioningConfig `
-Windows `
-DisableAutomaticUpdates `
-DisableWinRMHttps `
-NoRDPEndpoint `
-AdminUsername $vmAdminUserName `
-Password $vmAdminPassword |
Set-AzureSubnet `
-SubnetNames "ADNet" |
Add-AzureDataDisk `
-CreateNew `
-DiskSizeInGB "50" `
-MediaLocation $vmADVHDLocation `
-DiskLabel $vmADVHDName `
-LUN 0 `
-HostCaching "None" |
New-AzureVM `
-ServiceName $cloudServiceName `
-VNetName $virtualNetworkName
# Loop until Status = ReadyRole...
Write-Host "`tWaiting for Provisioning to Complete..."
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
While ($VMStatus.InstanceStatus -ne "ReadyRole")
{
write-host "`t`tWaiting...Current Status = " $VMStatus.InstanceStatus
Start-Sleep -Seconds 15
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
}
# DNS Variables...
Write-Host "Configuring DNS..."
$dnsChanged = 0
$virtualNetworkNamespace =
"http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration"
$networkTempPath = [IO.Path]::GetTempFileName()
$dcIPAddress = (Get-AzureVM -ServiceName $cloudServiceName -Name $vmName).IpAddress
# Remove Temporary File if It Exists...
if ((Test-Path $networkTempPath) -eq $true)
{
Remove-Item $networkTempPath
}
# Get the Azure Network Configuration File...
Get-AzureVNetConfig -ExportToFile $networkTempPath
[xml]$dnsNetwork = Get-Content $networkTempPath
# Check for DNS Node...
if ($dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns") -eq
$NULL)
{
$dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").AppendChild($dnsNetwor
k.CreateNode("element", "Dns", $virtualNetworkNamespace))
Page 29 of 86
$dnsChanged = 1
}
# Check for DnsServers Node...
if
($dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns").Item("Dns
Servers") -eq $NULL)
{
$dnsServersNode = $dnsNetwork.CreateNode("element", "DnsServers", $virtualNetworkNamespace)
$dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns").AppendChil
d($dnsServersNode)
$dnsChanged = 1
}
# Add DNS Server Entry...
if
(($dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns").Item("Dn
sServers").ChildNodes | Where {$_.Name -eq $vmName}) -eq $NULL)
{
$dnsServerNode = $dnsNetwork.CreateNode("element", "DnsServer", $virtualNetworkNamespace)
$dnsServerNode.SetAttribute("name", $vmName)
$dnsServerNode.SetAttribute("IPAddress", $dcIPAddress)
$dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns").Item("DnsS
ervers").AppendChild($dnsServerNode)
$dnsChanged = 1
}
# Add DNS Servers Reference...
$virtualNetwork =
$dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("VirtualNetworkSi
tes").ChildNodes | Where {$_.Name -eq $virtualNetworkName}
if ($virtualNetwork.Item("DnsServersRef") -eq $NULL)
{
$virtualNetwork.AppendChild($dnsNetwork.CreateNode("element", "DnsServersRef",
$virtualNetworkNamespace))
$dnsChanged = 1
}
# Add DNS Server Reference...
$dnsServerRef =
($dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("VirtualNetworkS
ites").ChildNodes | Where {$_.Name -eq $virtualNetworkName}).Item("DnsServersRef")
if (($dnsServerRef.ChildNodes | Where {$_.Name -eq $dnsServerName}) -eq $NULL)
{
$dnsServerRefNode = $dnsNetwork.CreateNode("element", "DnsServerRef", $virtualNetworkNamespace)
$dnsServerRefNode.SetAttribute("name", $vmName)
$dnsServerRef.AppendChild($dnsServerRefNode)
$dnsChanged = 1
}
# Save the Network Configuration...
$dnsNetwork.Save($networkTempPath)
# Update the Network Configuration...
if ($dnsChanged -eq 1)
{
Set-AzureVNetConfig -ConfigurationPath $networkTempPath
}
# Clean Up After Yourself...
Remove-Item $networkTempPath
14.1.2. Validation
There are two ways to verify that the virtual machine was created:

Portal – In the Windows Azure Management Portal, click Virtual Machines and then verify that the virtual
machine exists (you might need to refresh the page).
Page 30 of 86

PowerShell – Run the following Windows PowerShell command (include the same variable script block used to
run the command listed earlier). It should return the value True.
((Get-AzureVM -name "BIPaper-DC1" -ServiceName $cloudServiceName) -ne $NULL)
To validate that the DNS server entry was created, open the Windows Azure Management portal, select the network
used for this paper (BIPaper-Network is the default unless you used a different name) and navigate to the Configure
page. You should see an entry under dns servers for the domain controller that was just created and its IP address (you
might need to refresh the page).
The rest of the scripts for this domain controller are run while you are logged into the machine. Connect through remote
desktop (either through a public endpoint on the virtual machine or through a point-to-site VPN) before you run these
scripts.
14.1.3. Format Disks
This on-box script formats the disk that was created to host the Active Directory databases.
The script block requires that the following text be stored in a text file named “C:\Temp\DiskpartUnattended.txt”.
rescan
select
online
create
select
format
assign
disk 2
disk noerr
partition primary
part 1
quick
letter=Z:
After that file is created, run the following script in Windows PowerShell on the target machine (this script does not
require the variable block defined earlier).
diskpart /s ("C:\Temp\DiskpartUnattended.txt")
Validation
To verify that this command worked, start Windows Explorer and then verify that the Z:\ drive exists.
14.1.4. Create Domain
This command promotes the machine to a domain controller. There are four components to the script:



Get the Safe Mode Administrator Password – Prompts the user for the safe mode administrator password that
you want to use for the domain.
Install the Active Directory Feature – Installs the Windows feature for Active Directory Domain Services and also
installs the appropriate management tools.
Import the ADDS PowerShell Module – Imports the Windows PowerShell module for the feature that was just
installed so that it can be used for the next command.
Page 31 of 86

Promote the Domain Controller – Turns this server into a domain controller.
Run the following script in Windows PowerShell on the target machine using the on-box variable block defined earlier in
the document.
# Get the Safe Mode Administrator Password...
$password = Read-Host -AsSecureString -Prompt "Safe Mode Administrator Password"
# Install the Active Directory Feature...
Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools
# Import the ADDS PowerShell Module...
Import-Module ADDSDeployment
# Promote the Domain Controller...
Install-ADDSForest `
-DomainName $domainNameFQ `
-DomainNetbiosName $domainName `
-ForestMode "Win2012" `
-DomainMode "Win2012" `
-SafeModeAdministratorPassword $password `
-DatabasePath "Z:\Windows\NTDS" `
-LogPath "Z:\Windows\NTDS" `
-SysvolPath "Z:\Windows\SYSVOL" `
-InstallDns:$true `
-CreateDnsDelegation:$false `
-NoRebootOnCompletion:$true `
-Force:$true
Note: You will receive warnings about the server not having a static IP address. This is fine, because the IP address that is
assigned to a VM in Windows Azure, though it is dynamically assigned, has an infinite lease.
Note: After you promote the machine to a domain controller, you will need to log in with domain\username (using the
same user name you specified for the local machine administrator account).
After you run this command, restart the server.
Validation
To verify that this command worked:
1.
2.
3.
4.
Log in to the server.
Open Windows Explorer.
In the left-hand tree view, right-click Computer, and then click Properties.
In the window that is displayed, verify that the domain listed is what you set for the variable $domainNameFQ.
14.1.5. Create Sites and Subnets
This script will create the Active Directory sites and subnets to support the network configuration that we defined
earlier.
Run the following script in Windows PowerShell on the target machine using the on-box variable block defined earlier in
the document.
# Split FQDN...
$dc = ""
foreach ($part in $domainNameFQ.Split("."))
{
$dc += (",DC=" + $part)
}
# Import the Active Directory PowerShell Module...
Import-Module ActiveDirectory
# Create the Default Subnet...
New-ADObject `
Page 32 of 86
-Name '172.16.0.0/17' `
-Type subnet `
-Description 'DefaultSubnet' `
-Path "CN=Subnets,CN=Sites,CN=Configuration$dc" `
-OtherAttributes @{siteObject="CN=Default-First-Site-Name,CN=Sites,CN=Configuration$dc"}
# Create the DC Site...
New-ADObject `
-Name 'DC' `
-Type site `
-Path "CN=Sites,CN=Configuration$dc"
# Create the DCNet Subnet...
New-ADObject `
-Name '172.16.1.0/29' `
-Type subnet `
-Description 'DCNet' `
-Path "CN=Subnets,CN=Sites,CN=Configuration$dc" `
-OtherAttributes @{siteObject="CN=DC,CN=Sites,CN=Configuration$dc"}
# Create the DB Site...
New-ADObject `
-Name 'DB' `
-Type site `
-Path "CN=Sites,CN=Configuration$dc"
# Create the DBNet Subnet...
New-ADObject `
-Name '172.16.2.0/24' `
-Type subnet `
-Description 'DBNet' `
-Path "CN=Subnets,CN=Sites,CN=Configuration$dc" `
-OtherAttributes @{siteObject="CN=DB,CN=Sites,CN=Configuration$dc"}
# Create the App Site...
New-ADObject `
-Name 'App' `
-Type site `
-Path "CN=Sites,CN=Configuration$dc"
# Create the AppNet Subnet...
New-ADObject `
-Name '172.16.3.0/24' `
-Type subnet `
-Description 'AppNet' `
-Path "CN=Subnets,CN=Sites,CN=Configuration$dc" `
-OtherAttributes @{siteObject="CN=App,CN=Sites,CN=Configuration$dc"}
# Create the Web Site...
New-ADObject `
-Name 'Web' `
-Type site `
-Path "CN=Sites,CN=Configuration$dc"
# Create the WebNet Subnet...
New-ADObject `
-Name '172.16.4.0/24' `
-Type subnet `
-Description 'WebNet' `
-Path "CN=Subnets,CN=Sites,CN=Configuration$dc" `
-OtherAttributes @{siteObject="CN=Web,CN=Sites,CN=Configuration$dc"}
Validation
To verify that this command worked:
1.
2.
3.
4.
5.
Log in to the server.
Start Active Directory Sites and Services.
In the left-hand tree-view, expand the Sites node.
In the left-hand tree-view, you should see nodes for App, DB, DC, Default-First-Site-Name and Web.
In the left-hand tree-view, click Subnets.
Page 33 of 86
6. In the right-hand list-view, verify that the following subnet/name combinations are present:
 172.16.0.0/17 Default-First-Site-Name
 172.16.1.0/29 DC
 172.16.2.0/24 DB
 172.16.3.0/24 App
 172.16.4.0/24 Web
14.1.6. Remove Forwarder
When the server was promoted to a domain controller, the Windows Azure DNS server was added to the list of DNS
forwarders. It is not necessary to have it there, so it can be removed.
Run the following script in Windows PowerShell on the target machine using the on-box variable block defined earlier in
the document.
Get-DnsServerForwarder | Remove-DnsServerForwarder -Force
Validation
To verify that this command worked:
1. Log in to the server.
2. Start DNS Manager.
3. In the left-hand tree-view, right-click BIPaper-DC1 (or your server name if you have changed it from the default
used in the scripts), and then click Properties.
4. In the Properties dialog box, click Forwarders.
5. Verify that the list of forwarders is empty.
14.2.
Second Domain Controller
The second domain controller that we will create provides the high availability that is required for this environment. It
will serve as not only an Active Directory server, but also as an internal DNS server for name resolution between our
VMs. As with all of the virtual machines we will be creating, the first step is a Windows Azure PowerShell command that
runs off-box and creates the machine itself. The remaining steps are Windows PowerShell commands that run while you
are logged into the VM.
14.2.1. Provision VM
This is the only off-box task within the scope of creating the second domain controller. All other scripts are run in a
remote desktop session on the machine. This script consists of the following elements:


Variable Block – This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
VM Creation – This section (starting with the comment “Creating the virtual machine…”) consists of the
following Windows Azure commands:
 New-AzureVMConfig – This command begins the definition of the virtual machine. It sets the name, size,
image, vhd location and label, and availability set.
 Add-AzureProvisioningConfig – This command determines how Windows Azure should provision the VM
defined in the last command. It tells Windows Azure that this will be a Windows machine, that
automatic updates should be disabled (you can turn this back on if you want), that there should not be
endpoints for RDP or Remote Windows PowerShell, and what the administrator user and password
should be. Additionally, this command provides the information necessary to automatically join the
machine to our domain.
 Set-AzureSubnet – This command defines what subnet the virtual machine should be deployed into.
Page 34 of 86


Add-AzureDataDisk – This command attaches an empty disk to the virtual machine when it is created.
The command defines the size and storage location of the disk, as well as the LUN and cache setting.
 New-AzureVM – This command does the work of creating the virtual machine that was defined in the
earlier commands. In addition to the information gathered from the earlier commands, it defines the
cloud service and virtual network that should be used. The script loops until creation of the VM is
complete and writes a status to the screen every 15 seconds.
DNS Creation – This section (starting with the comment “DNS Variables…”) consists of the following sections:
 DNS Variables – A set of variables used to create a DNS entry in the virtual network.
 Get the Windows Azure Network Configuration File – Loads the current virtual network configuration.
 Check for DNS Node – Checks the network configuration XML for a DNS node and creates one if it does
not exist.
 Check for DnsServers Node – Checks the network configuration XML for a DnsServers node and creates
one if it does not exist.
 Add DNS Server Entry – Adds the newly created domain controller as an available DNS server.
 Add DNS Servers Reference – Checks the network configuration XML for a DnsServersRef node in the
paper’s virtual network and creates one if it does not exist.
 Add DNS Server Reference – Checks the network configuration XML for a DnsServerRef node in the
paper’s virtual network and creates one if it does not exist.
 Save the Network Configuration – Saves the network configuration XML.
 Update the Network Configuration – Uploads the updated network configuration to Windows Azure.
 Clean Up After Yourself – Cleans up the temporary file used for the network configuration.
To create the second domain controller, run the following Windows Azure PowerShell command (use the
variable/subscription block with the storage account defined).
# Get the name for the VM...
$vmName = "BIPaper-DC2"
# Get the admin user name for the VM...
$vmAdminUserName = Read-Host -Prompt "Server Administrator User Name"
# Ask for the password that should be used for the server and convert it to a format usable by the
commands...
$vmAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Server Administrator Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($vmAdminPasswordSecure)
$vmAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
# Get the domain admin user name...
$domainAdminUserName = Read-Host -Prompt "Domain Administrator User Name"
# Ask for the domain admin password and convert it to a format usable by the commands...
$domainAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Domain Administrator Password"
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($domainAdminPasswordSecure)
$domainAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Get the name of the VM Image to use...
$vmImageName = (Get-AzureVMImage | Where { $_.Category -eq "Microsoft Windows Server Group" -and
$_.Label -like "Windows Server 2012 Datacenter*" } | Sort-Object PublishedDate -Descending | SELECT
ImageName)[0].ImageName
# Set the location of the .vhd files...
$storageAccountContainer = "https://" + $storageAccountName + ".blob.core.windows.net/vhds/"
$vmVHDLocation = $storageAccountContainer + $vmName + ".vhd"
$vmADVHDLocation = $storageAccountContainer + $vmName + "_ADData.vhd"
$vmADVHDName = $vmName + " AD Data"
# Create the virtual machine...
Write-Host "Creating the VM..."
New-AzureVMConfig `
-Name $vmName `
Page 35 of 86
-InstanceSize Small `
-ImageName $vmImageName `
-MediaLocation $vmVHDLocation `
-DiskLabel "OS" `
-AvailabilitySetName "ADAvailabilitySet" |
Add-AzureProvisioningConfig `
-WindowsDomain `
-DisableAutomaticUpdates `
-DisableWinRMHttps `
-NoRDPEndpoint `
-Domain $domainName `
-JoinDomain $domainNameFQ `
-DomainPassword $domainAdminPassword `
-DomainUserName $domainAdminUserName `
-AdminUsername $vmAdminUserName `
-Password $vmAdminPassword |
Set-AzureSubnet `
-SubnetNames "ADNet" |
Add-AzureDataDisk `
-CreateNew `
-DiskSizeInGB "50" `
-MediaLocation $vmADVHDLocation `
-DiskLabel $vmADVHDName `
-LUN 0 `
-HostCaching "None" |
New-AzureVM `
-ServiceName $cloudServiceName
# Loop until Satus = ReadyRole...
Write-Host "`tWaiting for Provisioning to Complete..."
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
While ($VMStatus.InstanceStatus -ne "ReadyRole")
{
write-host "`t`tWaiting...Current Status = " $VMStatus.InstanceStatus
Start-Sleep -Seconds 15
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
}
# DNS Variables...
Write-Host "Configuring DNS..."
$dnsChanged = 0
$virtualNetworkNamespace =
"http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration"
$networkTempPath = [IO.Path]::GetTempFileName()
$dcIPAddress = (Get-AzureVM -ServiceName $cloudServiceName -Name $vmName).IpAddress
# Remove Temporary File if it Exists...
if ((Test-Path $networkTempPath) -eq $true)
{
Remove-Item $networkTempPath
}
# Get the Azure Network Configuration File...
Get-AzureVNetConfig -ExportToFile $networkTempPath
[xml]$dnsNetwork = Get-Content $networkTempPath
# Check for DNS Node...
if ($dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns") -eq
$NULL)
{
$dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").AppendChild($dnsNetwor
k.CreateNode("element", "Dns", $virtualNetworkNamespace))
$dnsChanged = 1
}
# Check for DnsServers Node...
if
($dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns").Item("Dns
Servers") -eq $NULL)
{
$dnsServersNode = $dnsNetwork.CreateNode("element", "DnsServers", $virtualNetworkNamespace)
$dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns").AppendChil
d($dnsServersNode)
$dnsChanged = 1
Page 36 of 86
}
# Add DNS Server Entry...
if
(($dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns").Item("Dn
sServers").ChildNodes | Where {$_.Name -eq $vmName}) -eq $NULL)
{
$dnsServerNode = $dnsNetwork.CreateNode("element", "DnsServer", $virtualNetworkNamespace)
$dnsServerNode.SetAttribute("name", $vmName)
$dnsServerNode.SetAttribute("IPAddress", $dcIPAddress)
$dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("Dns").Item("DnsS
ervers").AppendChild($dnsServerNode)
$dnsChanged = 1
}
# Add DNS Servers Reference...
$virtualNetwork =
$dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("VirtualNetworkSi
tes").ChildNodes | Where {$_.Name -eq $virtualNetworkName}
if ($virtualNetwork.Item("DnsServersRef") -eq $NULL)
{
$virtualNetwork.AppendChild($dnsNetwork.CreateNode("element", "DnsServersRef",
$virtualNetworkNamespace))
$dnsChanged = 1
}
# Add DNS Server Reference...
$dnsServerRef =
($dnsNetwork.Item("NetworkConfiguration").Item("VirtualNetworkConfiguration").Item("VirtualNetworkS
ites").ChildNodes | Where {$_.Name -eq $virtualNetworkName}).Item("DnsServersRef")
if (($dnsServerRef.ChildNodes | Where {$_.Name -eq $dnsServerName}) -eq $NULL)
{
$dnsServerRefNode = $dnsNetwork.CreateNode("element", "DnsServerRef", $virtualNetworkNamespace)
$dnsServerRefNode.SetAttribute("name", $vmName)
$dnsServerRef.AppendChild($dnsServerRefNode)
$dnsChanged = 1
}
# Save the Network Configuration...
$dnsNetwork.Save($networkTempPath)
# Update the Network Configuration...
if ($dnsChanged -eq 1)
{
Set-AzureVNetConfig -ConfigurationPath $networkTempPath
}
# Clean Up After Yourself...
Remove-Item $networkTempPath
Validation
There are two ways to verify that the Virtual Machine was created:

Portal – In the Windows Azure Management Portal, click Virtual Machines and then verify that the virtual
machine exists (you might need to refresh the page).

Windows PowerShell – Run the following Windows PowerShell command (include the same variable script
block used to run the command above). It should return the value True.
((Get-AzureVM -name "BIPaper-DC2" -ServiceName $cloudServiceName) -ne $NULL)
To verify that the DNS server entry was created, open the Windows Azure Management portal, select the network used
for this paper (BIPaper-Network is the default unless you used a different name) and navigate to the Configure page.
Page 37 of 86
You should see an entry under dns servers for the domain controller that was just created and its IP address (you might
need to refresh the page).
The rest of the scripts for this domain controller will be run while you are logged into the machine. Connect through
remote desktop (either through a public endpoint on the virtual machine or through a point-to-site VPN) before you run
these scripts.
14.2.2. Format Disks
This on-box script formats the disk that was created to host the Active Directory databases.
The script block requires that the following text be stored in a text file named “C:\Temp\DiskpartUnattended.txt”.
rescan
select
online
create
select
format
assign
disk 2
disk noerr
partition primary
part 1
quick
letter=Z:
After that file is created, run the following script in Windows PowerShell on the target machine (this script does not
require the variable block defined earlier).
diskpart /s ("C:\Temp\DiskpartUnattended.txt")
Validation
To verify that this command worked, start Windows Explorer and then verify that the Z:\ drive exists.
14.2.3. Create Domain Controller
This command promotes the machine to a domain controller. There are four components to the script:




Get the Safe Mode Administrator Password – Prompts the user for the safe mode administrator password that
they want to use for the domain. Provide the same password that was used when the domain was created with
the first domain controller.
Install the Active Directory Feature – Installs the Windows feature for Active Directory Domain Services and also
installs the appropriate management tools.
Import the ADDS PowerShell Module – Imports the Windows PowerShell module for the feature that was just
installed so that it can be used for the next command.
Promote the Domain Controller – Turns this server into a domain controller.
Run the following script in Windows PowerShell on the target machine using the on-box variable block defined earlier in
the document.
# Get the Safe Mode Administrator Password...
$password = Read-Host -AsSecureString -Prompt "Safe Mode Administrator Password"
# Install the Active Directory Feature...
Install-WindowsFeature -Name AD-Domain-Services -IncludeManagementTools
# Import the ADDS PowerShell Module...
Import-Module ADDSDeployment
# Promote the Domain Controller...
Install-ADDSDomainController `
-DomainName $domainNameFQ `
-SiteName "Default-First-Site-Name" `
-SafeModeAdministratorPassword $password `
-DatabasePath "z:\Windows\NTDS" `
-LogPath "z:\Windows\NTDS" `
-SysvolPath "z:\Windows\SYSVOL" `
-InstallDns:$true `
Page 38 of 86
-CreateDnsDelegation:$false `
-NoGlobalCatalog:$false `
-CriticalReplicationOnly:$false `
-NoRebootOnCompletion:$true `
-Force:$true
Note: You will receive warnings about the server not having a static IP address. This is fine, because the IP address that is
assigned to a VM in Windows Azure, though it is dynamically assigned, has an infinite lease.
Note: After you promote the machine to a domain controller, you will need to log in with domain\username (using the
same user name you specified for the local machine administrator account).
After you run this command, restart the server.
Validation
To verify that this command worked:
1.
2.
3.
4.
Log in to the server.
Open Windows Explorer.
In the left-hand tree view, right-click Computer, and then click Properties.
In the window that is displayed, verify that the domain listed is what you set for the variable $domainNameFQ.
14.2.4. Create Share
This on-box script creates a share that will be used as a quorum disk for the Windows Failover Cluster that will be
created in a later step.
Run the following script in Windows PowerShell on the target machine using the on-box variable block defined earlier in
the document.
# Create Quorum Share...
C:
CD \
mkdir Quorum
net share Quorum=c:\Quorum /grant`:Everyone`,CHANGE
Validation
To verify that this command worked:
1.
2.
3.
4.
5.
6.
Log in to the server.
Open Windows Explorer.
Browse to the root of C:\, and then verify that a directory named Quorum exists.
Right-click on the Quorum directory, and then click Properties.
In the Properties dialog box, select the Sharing tab.
Verify that directory is shared with the network path \\BIPaper-DC2\Quorum (or the name of the server that
you used in the script if you changed it).
7. Click Advanced Sharing, and then click Permissions.
8. Verify that the group Everyone has been granted Change permissions.
14.3.
Service User Accounts
In this step we will create a series of accounts that will be used to run the services that we create during the rest of the
paper. When we are finished, the following Active Directory objects will have been created:
Note: The values in bold in the list are names that are relied on through the rest of the paper. If you use different
names, you will need to adjust future scripts that use these names.
Page 39 of 86


Organizational Unit
 Name – Service Accounts
 Created In – BIPaper.local
User Accounts
 Name – DB1_SQL_Engine
 Organizational Unit – Service Accounts
 Display Name – DB1 SQL Server Engine Service Account
 SAM Account Name – DB1_SQL_Engine
 Name – DB1_SQL_Agent
 Organizational Unit – Service Accounts
 Display Name – DB1 SQL Server Agent Service Account
 SAM Account Name – DB1_SQL_Agent
 Name – DB2_SQL_Engine
 Organizational Unit – Service Accounts
 Display Name – DB2 SQL Server Engine Service Account
 SAM Account Name – DB2_SQL_Engine
 Name – DB2_SQL_Agent
 Organizational Unit – Service Accounts
 Display Name – DB2 SQL Server Agent Service Account
 SAM Account Name – DB2_SQL_Agent
 Name – SP_Farm
 Organizational Unit – Service Accounts
 Display Name – SharePoint Farm Service Account
 SAM Account Name – SP_Farm
 Name – SQL_Reporting
 Organizational Unit – Service Accounts
 Display Name – Reporting Services Service Account
 SAM Account Name – SQL_Reporting
 Name – PP1_PowerPivot
 Organizational Unit – Service Accounts
 Display Name – PP1 PowerPivot Service Account
 SAM Account Name – PP1_PowerPivot
 Name – PP2_PowerPivot
 Organizational Unit – Service Accounts
 Display Name – PP2 PowerPivot Service Account
 SAM Account Name – PP2_PowerPivot
The accounts created here are configured so that their passwords never expire. If you are using this paper to configure a
production environment, be sure to follow your organization’s password requirements.
14.3.1. Create Service User Accounts
Log in to one of the two domain controllers (either will work) and run the following script in Windows PowerShell using
the on-box variable block defined earlier in the document.
# Get the password for the service accounts...
$serviceAccountPassword = Read-Host -AsSecureString -Prompt "Service Account Password"
# Create an OU for the Accounts...
New-ADOrganizationalUnit -Name "Service Accounts"
$organizationalUnit = Get-ADOrganizationalUnit -Filter "Name -eq 'Service Accounts'"
Page 40 of 86
# Create the DB1 SQL Server Engine Account...
New-ADUser `
-Name "DB1_SQL_Engine" `
-AccountPassword $serviceAccountPassword `
-Path $organizationalUnit.DistinguishedName `
-ChangePasswordAtLogon 0 `
-DisplayName "DB1 SQL Server Engine Service Account" `
-Enabled 1 `
-PasswordNeverExpires 1 `
-SamAccountName "DB1_SQL_Engine"
# Create the DB1 SQL Server Agent Account...
New-ADUser `
-Name "DB1_SQL_Agent" `
-AccountPassword $serviceAccountPassword `
-Path $organizationalUnit.DistinguishedName `
-ChangePasswordAtLogon 0 `
-DisplayName "DB1 SQL Server Agent Service Account" `
-Enabled 1 `
-PasswordNeverExpires 1 `
-SamAccountName "DB1_SQL_Agent"
# Create the DB2 SQL Server Engine Account...
New-ADUser `
-Name "DB2_SQL_Engine" `
-AccountPassword $serviceAccountPassword `
-Path $organizationalUnit.DistinguishedName `
-ChangePasswordAtLogon 0 `
-DisplayName "DB2 SQL Server Engine Service Account" `
-Enabled 1 `
-PasswordNeverExpires 1 `
-SamAccountName "DB2_SQL_Engine"
# Create the DB2 SQL Server Agent Account...
New-ADUser `
-Name "DB2_SQL_Agent" `
-AccountPassword $serviceAccountPassword `
-Path $organizationalUnit.DistinguishedName `
-ChangePasswordAtLogon 0 `
-DisplayName "DB2 SQL Server Agent Service Account" `
-Enabled 1 `
-PasswordNeverExpires 1 `
-SamAccountName "DB2_SQL_Agent"
# Create the SharePoint Farm Account...
New-ADUser `
-Name "SP_Farm" `
-AccountPassword $serviceAccountPassword `
-Path $organizationalUnit.DistinguishedName `
-ChangePasswordAtLogon 0 `
-DisplayName "SharePoint Farm Service Account" `
-Enabled 1 `
-PasswordNeverExpires 1 `
-SamAccountName "SP_Farm"
# Create the Reporting Services Service Account...
New-ADUser `
-Name "SQL_Reporting" `
-AccountPassword $serviceAccountPassword `
-Path $organizationalUnit.DistinguishedName `
-ChangePasswordAtLogon 0 `
-DisplayName "Reporting Services Service Account" `
-Enabled 1 `
-PasswordNeverExpires 1 `
-SamAccountName "SQL_Reporting"
# Create the PP1 PowerPivot Service Account...
New-ADUser `
-Name "PP1_PowerPivot" `
-AccountPassword $serviceAccountPassword `
-Path $organizationalUnit.DistinguishedName `
-ChangePasswordAtLogon 0 `
-DisplayName "PP1 PowerPivot Service Account" `
-Enabled 1 `
-PasswordNeverExpires 1 `
-SamAccountName "PP1_PowerPivot"
Page 41 of 86
# Create the PP2 PowerPivot Service Account...
New-ADUser `
-Name "PP2_PowerPivot" `
-AccountPassword $serviceAccountPassword `
-Path $organizationalUnit.DistinguishedName `
-ChangePasswordAtLogon 0 `
-DisplayName "PP2 PowerPivot Service Account" `
-Enabled 1 `
-PasswordNeverExpires 1 `
-SamAccountName "PP2_PowerPivot"
Validation
To verify that this command was successful:
1.
2.
3.
4.
Log in to one of the domain controllers.
Start Active Directory Users and Computers.
In the left-hand tree view, expand BIPaper.local (or your domain name if you have changed it).
In the left-hand tree view, click Service Accounts, and then verify that the user accounts detailed in this section
appear in the right-hand list view.
To Overview of the deployment steps
Page 42 of 86
15.
Step 3: Configure SQL Server Database Servers (SharePoint Back End)
In the previous sections we built the foundation with the Windows Azure environment and the two domain controllers.
Now it is time to build the database servers (BiPaper-DB1 and BiPaper-DB2) that will support the SharePoint content
and configuration databases. In this environment two instances of SQL Server host an availability group that contains the
SharePoint databases. During this step we install the individual database servers, but we will configure AlwaysOn
Availability Groups; that will happen after SharePoint is installed.
At the end of this section, you will have an environment that looks like this:


First Database Server
o Server Name – BIPaper-DB1
o Storage Account – <your globally unique name>
o Domain/Forest Name – BIPaper.local
o Attached Disk – 250 GB for SQL Server (scripts format as S)
o Network Subnet – DBNet
o Availability Set - DBAvailabilitySet
o SQL Server installed as the default instance with the following settings:
 Features – SQL Server Engine, SQL Server Management Studio with Advanced Tools
 Instance directory on data drive
 Engine User Account – BIPaper\DB1_SQL_Engine
 Agent Startup Mode - Automatic
 Agent User Account – BIPaper\DB1_SQL_Agent
 Agent Startup Mode – Automatic
 Mixed Mode Security
 Domain Administrator Account set as system admin
 TCP Enabled
o Inbound TCP ports 1433 and 5022 open in firewall for domain networks
o Failover Clustering feature installed
Second Database Server
o Server Name – BIPaper-DB2
o Storage Account – <your globally unique name>
o Domain/Forest Name – BIPaper.local
o Attached Disk – 250GB for SQL Server (scripts format as S)
o Network Subnet – DBNet
o Availability Set - DBAvailabilitySet
o SQL Server installed as the default instance with the following settings:
 Features – SQL Server Engine, SQL Server Management Studio with Advanced Tools
 Instance directory on data drive
 Engine User Account – BIPaper\DB2_SQL_Engine
 Agent Startup Mode - Automatic
 Agent User Account – BIPaper\DB2_SQL_Agent
 Agent Startup Mode – Automatic
 Mixed Mode Security
 Domain Administrator Account set as system admin
 TCP Enabled
o Inbound TCP ports 1433 and 5022 open in firewall for domain networks
o Failover Clustering feature installed
Page 43 of 86
If you feel comfortable creating this environment on your own, you can do so and then skip to the “Step 4: configure
SQL Server PowerPivot Servers” section.
Important: This step requires installation media for SQL Server 2012 SP1 and at least
http://support.microsoft.com/kb/2833645/en-us. Place the information in the following directories on the VM:


D:\SQL Server 2012\ – This should be the contents of the SQL Server installation media (use the media with SP1
slipstreamed). Do not just put the .iso file in this directory—it needs to be the contents of the media extracted.
D:\SQL Server 2012 CU\ – This should be the .exe file that you would run to apply the CU. The CUs are delivered
as executable .zip files, the contents of which are what we are looking for in this directory.
Tip: When we configured this environment for the first time, we loaded all of the bits on a share on the first domain
controller. Then when we needed to install software, we copied the bits to the local D:\ drive from the share.
15.1.
First SQL Server Instance
The first SQL Server instance that we create will provide the landing zone for the databases that will be created during
the configuration of our SharePoint farm. As with all of the virtual machines we will be creating, the first step is a
Windows Azure PowerShell command that runs off-box and creates the machine itself. The remaining steps will be
Windows PowerShell commands that are run while you are logged into the VM.
15.1.1. Provision VM
This is the only off-box task within the scope of creating the first instance of SQL Server. All other scripts will be run in a
remote desktop session on the machine. The script consists of the following elements:


Variable Block – This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
VM Creation – This section (starting with the comment “Creating the virtual machine…”) consists of the
following Windows Azure commands:
o New-AzureVMConfig – This command begins the definition of the virtual machine. It sets the name, size,
image, .vhd location and label, and availability set.
o Add-AzureProvisioningConfig – This command determines how Windows Azure should provision the VM
defined in the last command. It tells Windows Azure that this will be a Windows machine, that
automatic updates should be disabled (you can turn this back on if you want), that there should not be
endpoints for RDP or Remote Windows PowerShell, and what the administrator user and password
should be. Additionally, this command provides the information necessary to automatically join the
machine to our domain.
o Set-AzureSubnet – This command defines what subnet the virtual machine should be deployed into.
o Add-AzureDataDisk – This command attaches an empty disk to the virtual machine when it is created.
The command defines the size and storage location of the disk, as well as the LUN and cache setting.
o New-AzureVM – This command does the work of creating the virtual machine that was defined in the
earlier commands. In addition to the information gathered from the earlier commands, it defines the
cloud service that should be used. The script loops until creation of the VM is complete and writes a
status to the screen every 15 seconds.
To create the first instance of SQL Server, run the following Windows Azure PowerShell command (use the
variable/subscription block with the storage account defined).
# Get the name for the VM...
$vmName = "BIPaper-DB1"
# Get the admin user name for the VM...
$vmAdminUserName = Read-Host -Prompt "Server Administrator User Name"
Page 44 of 86
# Ask for the password that should be used for the server and convert it to a format usable by the
commands...
$vmAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Server Administrator Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($vmAdminPasswordSecure)
$vmAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
# Get the domain admin user name...
$domainAdminUserName = Read-Host -Prompt "Domain Administrator User Name"
# Ask for the domain admin password and convert it to a format usable by the commands...
$domainAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Domain Administrator Password"
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($domainAdminPasswordSecure)
$domainAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Get the name of the VM Image to use...
$vmImageName = (Get-AzureVMImage | Where { $_.Category -eq "Microsoft Windows Server Group" -and
$_.Label -like "Windows Server 2012 Datacenter*" } | Sort-Object PublishedDate -Descending | SELECT
ImageName)[0].ImageName
# Set the location of the .vhd files...
$storageAccountContainer = "https://" + $storageAccountName + ".blob.core.windows.net/vhds/"
$vmVHDLocation = $storageAccountContainer + $vmName + ".vhd"
$vmSQLVHDLocation = $storageAccountContainer + $vmName + "_SQLData.vhd"
$vmSQLVHDName = $vmName + " SQL Data"
# Create the virtual machine...
Write-Host "Creating the VM..."
New-AzureVMConfig `
-Name $vmName `
-InstanceSize ExtraLarge `
-ImageName $vmImageName `
-MediaLocation $vmVHDLocation `
-DiskLabel "OS" `
-AvailabilitySetName "DBAvailabilitySet" |
Add-AzureProvisioningConfig `
-WindowsDomain `
-DisableAutomaticUpdates `
-DisableWinRMHttps `
-NoRDPEndpoint `
-Domain $domainName `
-JoinDomain $domainNameFQ `
-DomainPassword $domainAdminPassword `
-DomainUserName $domainAdminUserName `
-AdminUsername $vmAdminUserName `
-Password $vmAdminPassword |
Set-AzureSubnet `
-SubnetNames "DBNet" |
Add-AzureDataDisk `
-CreateNew `
-DiskSizeInGB "250" `
-MediaLocation $vmSQLVHDLocation `
-DiskLabel $vmSQLVHDName `
-LUN 0 `
-HostCaching "None" |
New-AzureVM `
-ServiceName $cloudServiceName
# Loop until Satus = ReadyRole...
Write-Host "`tWaiting for Provisioning to Complete..."
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
While ($VMStatus.InstanceStatus -ne "ReadyRole")
{
write-host "`t`tWaiting...Current Status = " $VMStatus.InstanceStatus
Start-Sleep -Seconds 15
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
}
Validation
There are two ways to verify that the virtual machine was created:
Page 45 of 86

Portal – In the Windows Azure Management Portal, click Virtual Machines and then verify that the virtual
machine exists (you might need to refresh the page).

Windows PowerShell – Run the following Windows PowerShell command (include the same variable script
block used to run the command above). It should return the value True.
((Get-AzureVM -name "BIPaper-DB1" -ServiceName $cloudServiceName) -ne $NULL)
15.2.
Format Disks
This on-box script formats the disk that was created to host the SQL Server installation.
The script block requires that the following text be stored in a text file named “C:\Temp\DiskpartUnattended.txt”.
rescan
select
online
create
select
format
assign
disk 2
disk noerr
partition primary
part 1
quick
letter=S:
After that file is created, run the following script in Windows PowerShell on the target machine (this script does not
require the variable block defined earlier).
diskpart /s ("C:\Temp\DiskpartUnattended.txt")
Validation
To verify that this command worked, start Windows Explorer and then verify that the S:\ drive exists.
15.3.
Enable Clustering
This on-box script enables Windows Clustering, which is required to support AlwaysOn Availability Groups (configured in
a later process). This script does not require the variable block defined earlier.
Add-WindowsFeature Failover-Clustering -IncludeManagementTools
Validation
To verify that this command worked, log in to the server and then run the following Windows PowerShell command. It
should return the value True.
((Get-WindowsFeature | where {$_.Name -eq "Failover-Clustering" -and $_.InstallState -eq
"Installed"}) -ne $NULL)
15.4.
Install SQL Server
This on-box script installs the SQL Server engine and opens the required firewall ports. You are prompted for the
passwords of the service accounts (DB1_SQL_Agent and DB1_SQL_Engine), the password that you want to use for the sa
account, the domain administrator user name to make a SQL Server system administrator, and the license key for your
SQL Server media.
Page 46 of 86
Important: Don’t forget to copy your installation media to the directories listed earlier in this section before you run
this script.
Run the following script in Windows PowerShell on the target machine using the on-box variable block defined earlier in
the document.
# Script-level variables...
$agentAccountUserName = "DB1_SQL_Agent"
$engineAccountUserName = "DB1_SQL_Engine"
# Get domain admin user...
$domainAdminUser = Read-Host -Prompt "Domain Administrator User Name"
# Get the passwords...
$agentServicePasswordSecure = Read-Host -AsSecureString -Prompt "Agent Service Account
($agentAccountUserName) Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($agentServicePasswordSecure)
$agentServicePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
$engineServicePasswordSecure = Read-Host -AsSecureString -Prompt "Engine Service Account
($engineAccountUserName) Password"
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($engineServicePasswordSecure)
$engineServicePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
$saPasswordSecure = Read-Host -AsSecureString -Prompt "SA Password"
$stringMarshal3 = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($saPasswordSecure)
$saPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal3)
# Get the SQL Server license key...
$sqlpid = Read-Host -Prompt "SQL Server License Key"
# Install SQL Server...
D:
CD "\SQL Server 2012"
.\setup.exe `
/Action=Install `
/ENU `
/UpdateEnabled=1 `
/UpdateSource="D:\SQL Server 2012 CU" `
/ErrorReporting=0 `
/Features=SQLEngine,SSMS,ADV_SSMS `
/IndicateProgress `
/InstanceName=MSSQLServer `
/InstanceDir=S:\SQL\ `
/QS `
/SQLSvcAccount=$domainName\$engineAccountUserName `
/SQLSvcPassword=$engineServicePassword `
/SQLSvcStartupType=Automatic `
/AGTSvcAccount=$domainName\$agentAccountUserName `
/AGTSvcPassword=$agentServicePassword `
/AGTSvcStartupType=Automatic `
/SecurityMode=SQL `
/SAPwd=$saPassword `
/SQLSysAdminAccounts=$domainName\$domainAdminUser `
/TCPEnabled=1 `
/PID="$sqlpid" `
/IACCEPTSQLSERVERLICENSETERMS
# Open firewall ports...
netsh advfirewall firewall add rule name="SQL Server inbound on TCP 1433" dir=in action=allow
protocol=TCP localport=1433 profile=domain
netsh advfirewall firewall add rule name="SQL Server Mirroring inbound on TCP 5022" dir=in
action=allow protocol=TCP localport=5022 profile=domain
Validation
Follow these steps to verify that this command worked:
Page 47 of 86
1. Check the services. Log in to the server, open Services, and then in the right-hand list view, verify that SQL
Server (MSSQLSERVER) exists, is running, is set to start up automatically, and is running as the
DB1_SQL_Engine account.
2. Verify that SQL Server Agent (MSSQLSERVER) exists, is running, is set to start up automatically, and is
running at the DB1_SQL_Agent account.
3. Check the log. Log in to the server, open the summary.txt file (found at C:\Program Files\Microsoft SQL
Server\110\Setup Bootstrap\Log), and then verify that the Final result is Passed and the Exit code (Decimal)
is 0.
4. Check the firewall. Log in to the server, open the Windows Firewall control panel, and then click Advanced
settings.
5. In the Windows Firewall with Advanced Security window, in the left-hand tree view, click Inbound Rules.
6. Verify that “SQL Server inbound on TCP 1433” exists, is set for the Domain profile, and is enabled. Verify that
the local port is 1433.
7. Verify that “SQL Server Mirroring inbound on TCP 5022” exists, is set for the Domain profile, and is enabled.
Verify that the local port is 5022.
15.5.
Second SQL Server Instance
To install the second instance of SQL Server that is required for this infrastructure, repeat all of the steps for installing
the first instance of SQL Server, but replace the text DB1 with DB2 (including in the validation steps).
To Overview of the deployment steps
Page 48 of 86
16.
Step 4: Configure SQL Server PowerPivot Servers
In this section we will install the Analysis Services SharePoint mode instances (BiPaper-PP1, BiPaper-PP2) to support
loading PowerPivot models stored in Excel workbooks. As with all of the other server roles in this document, we will
configure two of these servers to provide high availability. Additionally, SharePoint will use both of the servers to load
models so having more than one server will increase your system’s performance.
Note: Although we are only installing two servers during this step, you can use more than two servers if you want to
improve performance.
At the end of this section, you will have an environment that looks like the following:


First PowerPivot Server
o Server Name – BIPaper-PP1
o Storage Account – <your globally unique name>
o Domain/Forest Name – BIPaper.local
o Network Subnet – DBNet
o Availability Set – PPAvailabilitySet
o SQL Server PowerPivot installation
 Role – SharePoint Existing Farm
 Instance Name - PowerPivot
 Analysis Services Engine Account – BIPaper\PP1_PowerPivot
 Analysis Services Startup Mode – Automatic
 Analysis Services Administrator Accounts
 Domain Administrator Account
 BIPaper\SP_Farm
 BIPaper\SQL_Reporting
 Listening on static port 2383
o Inbound TCP ports 2382 and 2383 open in firewall for domain networks
Second PowerPivot Server
o Server Name – BIPaper-PP2
o Storage Account – <your globally unique name>
o Domain/Forest Name – BIPaper.local
o Network Subnet – DBNet
o Availability Set – PPAvailabilitySet
o SQL Server PowerPivot installation
 Role – SharePoint Existing Farm
 Instance Name - PowerPivot
 Analysis Services Engine Account – BIPaper\PP2_PowerPivot
 Analysis Services Startup Mode – Automatic
 Analysis Services Administrator Accounts
 Domain Administrator Account
 BIPaper\SP_Farm
 BIPaper\SQL_Reporting
 Listening on static port 2383
o Inbound TCP ports 2382 and 2383 open in firewall for domain networks
If you feel comfortable creating this environment on your own, you can do so and then skip to the “Configure First
SharePoint Application/Central Administration Server” section.
Page 49 of 86
Important: This step requires installation media for SQL Server 2012 SP1 and at least SQL Server 2012 SP1 CU4.
Place the information in the following directories on the VM:


D:\SQL Server 2012\ – This should be the contents of the SQL Server installation media (use the media with SP1
slipstreamed). Do not just put the .iso file in this directory—it needs to be the contents of the media extracted.
D:\SQL Server 2012 CU\ – This should be the .exe file that you would run to apply the CU. The CUs are delivered
as executable .zip files, the contents of which are what we are looking for in this directory.
Tip: When we configured this environment for the first time, we loaded all of the bits on a share on the first domain
controller. Then when we needed to install software, we copied the bits to the local D:\ drive from the share.
16.1.
First PowerPivot Server
The PowerPivot servers that we create in this section will be added to SharePoint in the next section where we configure
the farm. As with all of the virtual machines we will be creating, the first step is a Windows Azure PowerShell command
that runs off-box and creates the machine itself. The remaining steps will be Windows PowerShell commands that run
while you are logged into the VM.
16.1.1. Provision VM
This is the only off-box task within the scope of creating the first PowerPivot server. All other scripts run in a remote
desktop session on the machine. The script consists of the following elements:


Variable Block – This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
VM Creation – This section (starting with the comment “Creating the virtual machine…”) consists of the
following Windows Azure commands:
o New-AzureVMConfig – This command begins the definition of the virtual machine. It sets the name, size,
image, .vhd location and label, and availability set.
o Add-AzureProvisioningConfig – This command determines how Windows Azure should provision the VM
defined in the last command. It tells Windows Azure that this will be a Windows machine, that
automatic updates should be disabled (you can turn this back on if you want), that there should not be
endpoints for RDP or Remote Windows PowerShell, and what the administrator user and password
should be. Additionally, this command provides the information necessary to automatically join the
machine to our domain.
o Set-AzureSubnet – This command defines what subnet the virtual machine should be deployed into.
o New-AzureVM – This command creates the virtual machine that was defined in the earlier commands. In
addition to the information gathered from the earlier commands, it defines the cloud service that
should be used. The script loops until creation of the VM is complete and writes a status to the screen
every 15 seconds.
To create the first PowerPivot server, run the following Windows Azure PowerShell command (use the
variable/subscription block with the storage account defined).
# Get the name for the VM...
$vmName = "BIPaper-PP1"
# Get the admin user name for the VM...
$vmAdminUserName = Read-Host -Prompt "Server Administrator User Name"
# Ask for the password that should be used for the server and convert it to a format usable by the
commands...
$vmAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Server Administrator Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($vmAdminPasswordSecure)
$vmAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
Page 50 of 86
# Get the domain admin user name...
$domainAdminUserName = Read-Host -Prompt "Domain Administrator User Name"
# Ask for the domain admin password and convert it to a format usable by the commands...
$domainAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Domain Administrator Password"
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($domainAdminPasswordSecure)
$domainAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Get the name of the VM Image to use...
$vmImageName = (Get-AzureVMImage | Where { $_.Category -eq "Microsoft Windows Server Group" -and
$_.Label -like "Windows Server 2012 Datacenter*" } | Sort-Object PublishedDate -Descending | SELECT
ImageName)[0].ImageName
# Set the location of the .vhd files...
$storageAccountContainer = "https://" + $storageAccountName + ".blob.core.windows.net/vhds/"
$vmVHDLocation = $storageAccountContainer + $vmName + ".vhd"
# Create the virtual machine...
Write-Host "Creating the VM..."
New-AzureVMConfig `
-Name $vmName `
-InstanceSize ExtraLarge `
-ImageName $vmImageName `
-MediaLocation $vmVHDLocation `
-DiskLabel "OS" `
-AvailabilitySetName "PPAvailabilitySet" |
Add-AzureProvisioningConfig `
-WindowsDomain `
-DisableAutomaticUpdates `
-DisableWinRMHttps `
-NoRDPEndpoint `
-Domain $domainName `
-JoinDomain $domainNameFQ `
-DomainPassword $domainAdminPassword `
-DomainUserName $domainAdminUserName `
-AdminUsername $vmAdminUserName `
-Password $vmAdminPassword |
Set-AzureSubnet `
-SubnetNames "DBNet" |
New-AzureVM `
-ServiceName $cloudServiceName
# Loop until Satus = ReadyRole...
Write-Host "`tWaiting for Provisioning to Complete..."
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
While ($VMStatus.InstanceStatus -ne "ReadyRole")
{
write-host "`t`tWaiting...Current Status = " $VMStatus.InstanceStatus
Start-Sleep -Seconds 15
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
}
Validation
There are two ways to verify that the virtual machine was created:

Portal – In the Windows Azure Management Portal, click Virtual Machines and then verify that the virtual
machine exists (you might need to refresh the page).

PowerShell – Run the following Windows PowerShell command (include the same variable script block used to
run the command above). It should return the value True.
((Get-AzureVM -name "BIPaper-PP1" -ServiceName $cloudServiceName) -ne $NULL)
Page 51 of 86
16.1.2. Install SQL Server
This on-box script installs the Analysis Services PowerPivot instance and opens the required firewall ports. You are
prompted for the password for the service account (PP1_PowerPivot), the domain administrator user name to make an
Analysis Services administrator, and the license key for your SQL Server media.
Important: Don’t forget to copy your installation media to the directories listed earlier in this section before you run
this script.
Run the following script in Windows PowerShell on the target machine using the on-box variable block defined earlier in
the document.
# Script-level variables...
$engineAccountUserName = "PP1_PowerPivot"
# Get domain admin user...
$domainAdminUser = Read-Host -Prompt "Domain Administrator User Name"
# Get the passwords...
$engineServicePasswordSecure = Read-Host -AsSecureString -Prompt "PowerPivot Service Account
($engineAccountUserName) Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($engineServicePasswordSecure)
$engineServicePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
# Get the SQL Server license key...
$sqlpid = Read-Host -Prompt "SQL Server License Key"
# Install .NET 3.5...
Add-WindowsFeature -Name "NET-Framework-Core"
# Install SQL Server...
D:
CD "\SQL Server 2012"
.\setup.exe `
/Action=Install `
/ENU `
/UpdateEnabled=1 `
/UpdateSource="D:\SQL Server 2012 CU" `
/ErrorReporting=0 `
/IndicateProgress `
/InstanceName=POWERPIVOT `
/QS `
/SQMReporting=0 `
/ASSvcAccount=$env:USERDOMAIN\$engineAccountUserName `
/ASSvcPassword=$engineServicePassword `
/ASSvcStartupType=Automatic `
/ASSysAdminAccounts=$env:USERDOMAIN\$domainAdminUser, $env:USERDOMAIN\SP_Farm,
$env:USERDOMAIN\SQL_Reporting `
/ROLE=SPI_AS_ExistingFarm `
/PID="$sqlpid" `
/IAcceptSQLServerLicenseTerms
# Set the Analysis Services Port to 2383...
Stop-Service "MSOLAP`$POWERPIVOT"
[xml]$configAS = Get-Content "C:\Program Files\Microsoft SQL
Server\MSAS11.POWERPIVOT\OLAP\Config\msmdsrv.ini"
$configAS.ConfigurationSettings.Port = "2383"
$configAS.Save("C:\Program Files\Microsoft SQL Server\MSAS11.POWERPIVOT\OLAP\Config\msmdsrv.ini")
Start-Service "MSOLAP`$POWERPIVOT"
# Open the Firewall...
netsh advfirewall firewall add rule name="Analysis Services inbound on TCP 2383" dir=in
action=allow protocol=TCP localport=2383 profile=domain
netsh advfirewall firewall add rule name="SQL Browser inbound on TCP 2382" dir=in action=allow
protocol=TCP localport=2382 profile=domain
Validation
Follow these steps to validate that this command worked:
Page 52 of 86
1) Check the services. Log in to the server, start Services, and then in the right-hand list view, verify that “SQL
Server Analysis Services (POWERPIVOT)” exists, is running, is set to start up automatically, and is running as the
PP1_PowerPivot account.
2) Verify that “SQL Server Browser” exists, is running, and is set to start up automatically.
3) Check the log. Log in to the server, open the summary.txt file (found at C:\Program Files\Microsoft SQL
Server\110\Setup Bootstrap\Log), and then verify that the Final result is Passed and the Exit code (Decimal) is 0.
4) Check the configuration file. Log in to the server, and then open the msmdsrv.ini file (found at C:\Program
Files\Microsoft SQL Server\MSAS11.POWERPIVOT\OLAP\Config).
5) Find the ConfigurationSettings\Port node, and then verify that the value of the port node is set to 2383.
6) Check the firewall. Log in to the server, open the Windows Firewall control panel, and then click Advanced
settings.
7) In the left-hand tree view of the Windows Firewall with Advanced Security window, click Inbound Rules.
8) Verify that “Analysis Services inbound on TCP 2383” exists, is set for the Domain profile, and is enabled. Verify
that the local port is 2383.
9) Verify that “SQL Browser inbound on TCP 2382” exists, is set for the Domain profile, and is enabled. Verify that
the local port is 2382.
16.2.
Second PowerPivot Server
To install the second PowerPivot server that is required for this infrastructure, repeat all of the steps for installing the
first PowerPivot server, but replace the text PP1 with PP2 (including in the validation steps).
To Overview of the deployment steps
Page 53 of 86
17.
Step 5: Deploy the first SharePoint Application/Central Administration Server
In this section we will create the SharePoint farm. In this step, we will only configure the first of the SharePoint
application-tier servers (BiPapr-App1). The second server (for high availability) will be configured later in the document.
This section is divided into two parts—image creation and installation. In the image creation part we will create a
sysprepped image that will be used to create all of the SharePoint servers that we deploy. This will save time and also
ensure that all of your servers are configured identically.
17.1.
SharePoint Image
The SharePoint image that we will be creating will be stored as a VM image in Windows Azure that can be used to create
additional VMs. If you have used sysprepped VMs in your data center, this process should be fairly familiar to you.
When this step is complete, we will have the following:

SharePoint Image in Windows Azure
o Image Name – BIPaper-SharePoint
o Storage Account – <your globally unique name>
o Software:
 SharePoint 2013 Prerequisites
 SharePoint 2013 Enterprise (with desired patches)
 SQL Server 2012 RS Add-In (SP1)
 PowerPivot Add-In (2012 SP1 version)
If you feel comfortable creating and capturing this image on your own, you can do so and then skip to the “First
SharePoint Server” step in this section.
Note: This step requires installation media for SharePoint 2013, the PowerPivot Add-In (SQL Server 2012 SP1), and the
Reporting Services Add-In (SQL Server 2012 SP1). Place the information in the following directories on the VM:



D:\SharePoint 2013\ - This should be the contents of the SharePoint installation media. Do not just put the .iso
file in this directory – it needs to be the contents of the media extracted.
D:\spPowerPivot.msi – This should be the .msi file for installing the PowerPivot Add-In (SQL Server 2012 SP1).
D:\rsSharePoint.msi – This should be the .msi file for installing the Reporting Services Add-In (SQL Server 2012
SP1).
Important: If you do not use the SQL Server 2012 SP1 versions of these add-ins you will run into version compatibility
issues.
17.1.1. Provision VM
This is the first of two off-box tasks within the scope of creating the SharePoint image. The script consists of the
following elements:


Variable Block: This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
VM Creation: This section (starting with the comment “Creating the virtual machine…”) consists of the following
Windows Azure commands:
o New-AzureVMConfig – This command begins the definition of the virtual machine. It sets the name, size,
image, .vhd location and label, and availability set.
o Add-AzureProvisioningConfig – This command determines how Windows Azure should provision the VM
defined in the last command. It tells Windows Azure that this will be a Windows machine, that
automatic updates should be disabled (you can turn this back on if you want), that there should not be
Page 54 of 86
o
o
endpoints for RDP or Remote Windows PowerShell, and what the administrator user and password
should be. Additionally, this command provides the information necessary to automatically join the
machine to our domain.
Set-AzureSubnet: This command defines what subnet the virtual machine should be deployed into.
New-AzureVM: This command does the work of creating the virtual machine that was defined in the
earlier commands. In addition to the information gathered from the earlier commands, it defines the
cloud service that should be used. The script loops until creation of the VM is complete and writes a
status to the screen every 15 seconds.
To create the SharePoint image server, run the following Windows Azure PowerShell command (use the
variable/subscription block with the storage account defined).
# Get the name for the VM...
$vmName = "BIPaper-SP"
# Get the admin user name for the VM...
$vmAdminUserName = Read-Host -Prompt "Server Administrator User Name"
# Ask for the password that should be used for the server and convert it to a format usable by the
commands...
$vmAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Server Administrator Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($vmAdminPasswordSecure)
$vmAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
# Get the domain admin user name...
$domainAdminUserName = Read-Host -Prompt "Domain Administrator User Name"
# Ask for the domain admin password and convert it to a format usable by the commands...
$domainAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Domain Administrator Password"
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($domainAdminPasswordSecure)
$domainAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Get the name of the VM Image to use...
$vmImageName = (Get-AzureVMImage | Where { $_.Category -eq "Microsoft Windows Server Group" -and
$_.Label -like "Windows Server 2012 Datacenter*" } | Sort-Object PublishedDate -Descending | SELECT
ImageName)[0].ImageName
# Set the location of the .vhd files...
$storageAccountContainer = "https://" + $storageAccountName + ".blob.core.windows.net/vhds/"
$vmVHDLocation = $storageAccountContainer + $vmName + ".vhd"
# Create the virtual machine...
Write-Host "Creating the VM..."
New-AzureVMConfig `
-Name $vmName `
-InstanceSize ExtraLarge `
-ImageName $vmImageName `
-MediaLocation $vmVHDLocation `
-DiskLabel "OS" `
-AvailabilitySetName "AppAvailabilitySet" |
Add-AzureProvisioningConfig `
-WindowsDomain `
-DisableAutomaticUpdates `
-DisableWinRMHttps `
-NoRDPEndpoint `
-Domain $domainName `
-JoinDomain $domainNameFQ `
-DomainPassword $domainAdminPassword `
-DomainUserName $domainAdminUserName `
-AdminUsername $vmAdminUserName `
-Password $vmAdminPassword |
Set-AzureSubnet `
-SubnetNames "AppNet" |
New-AzureVM `
-ServiceName $cloudServiceName
# Loop until Satus = ReadyRole...
Write-Host "`tWaiting for Provisioning to Complete..."
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
Page 55 of 86
While ($VMStatus.InstanceStatus -ne "ReadyRole")
{
write-host "`t`tWaiting...Current Status = " $VMStatus.InstanceStatus
Start-Sleep -Seconds 15
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
}
Validation
There are two ways to verify that the virtual machine was created:

Portal – In the Windows Azure Management Portal, click Virtual Machines and then verify that the virtual
machine exists (you might need to refresh the page).

Windows PowerShell – Run the following Windows PowerShell command (include the same variable script
block used to run the command above). It should return the value True.
((Get-AzureVM -name "BIPaper-SP" -ServiceName $cloudServiceName) -ne $NULL)
17.1.2. Install SharePoint Prerequisites
These on-box steps install the SharePoint prerequisites on the machine that will be used as the image. This process will
require you to restart the server twice, manually.
Important: Don’t forget to copy your installation media to the locations listed earlier in this section before you run this
script.
Perform the following steps on the target server:
1) Run the following script in Windows PowerShell on the target machine (no variable block is required).
D:
CD "SharePoint 2013"
.\prerequisiteinstaller.exe /unattended
Wait-Process PrerequisiteInstaller
2) Restart the server.
3) Run the following script in Windows PowerShell on the target machine (no variable block is required).
D:
CD "SharePoint 2013"
.\prerequisiteinstaller.exe /unattended /continue
Wait-Process PrerequisiteInstaller
4) Restart the server.
5) Run the following script in Windows PowerShell on the target machine (no variable block is required).
D:
CD "SharePoint 2013"
.\prerequisiteinstaller.exe /unattended /continue
Wait-Process PrerequisiteInstaller
Page 56 of 86
Validation
To verify that the prerequisites were installed properly, log in to the server and then run the SharePoint 2013
Prerequisite Installer (D:\SharePoint 2013\PrerequisiteInstaller.exe). Step through the wizard to verify that all of the
options have been installed.
17.1.3. Install SharePoint
This on-box script installs the SharePoint bits on the target server.
Important: Don’t forget to copy your installation media to the locations listed earlier in this section before you run this
script.
Note: You will need to enter your license key into the file located at D:\SharePoint
2013\Files\SetupFarmSilent\Config.xml. If you do not provide the license key, the automated installation will not work.
The key needs to be placed in the PIDKEY node (where the file says Enter Product Key Here) and that node needs to be
uncommented.
Run the following script in Windows PowerShell on the target machine (no variable block is required).
D:
CD "SharePoint 2013"
.\Setup.exe /config Files\SetupFarmSilent\Config.xml # TODO: make sure that you put your license
key into this file...
Wait-Process Setup
Validation
To verify that SharePoint was installed:
1) Log in to the server.
2) In Control Panel, open Programs and Features.
3) Verify that Microsoft SharePoint Server 2013 shows up in the list.
17.1.4. Install Add-Ins
These on-box steps install the PowerPivot and Reporting Services add-ins on the machine that will be used as the image.
Important: Don’t forget to copy your installation media to the locations listed earlier in this section before you run this
script.
Perform the following steps on the target server:
1) Run the following script in Windows PowerShell on the target machine (no variable block is required; you will
need to wait for the installation dialog box to close before you proceed to the next step).
D:
CD \
.\rsSharePoint.msi /passive
2) Run the following script in Windows PowerShell on the target machine (no variable block is required; you will
need to wait for the installation dialog box to close before you proceed to the next step).
D:
CD\
.\spPowerPivot.msi /passive
Page 57 of 86
Validation
To verify that the add-ins were installed:
1)
2)
3)
4)
Log in to the server.
In Control Panel, open Programs and Features.
Verify that Microsoft SQL Server 2012 PowerPivot for SharePoint 2013 shows up in the list.
Verify that Microsoft SQL Server 2012 RS Add-in for SharePoint shows up in the list.
17.1.5. Install Updates
Because the updates that you choose to install are your choice, we will not be providing scripts for installing the
updates. For the paper, we chose to install the SharePoint Server 2013 March 2013 CU and the SharePoint Server 2013
April 2013 CU, but the updates that you install are entirely up to you.
17.1.6. Sysprep
This on-box script prepares the server for being made into a template.
Run the following script in Windows PowerShell on the target machine (no variable block is required).
C:
cd \windows\system32\sysprep
.\sysprep /generalize /oobe /shutdown
Validation
This script is designed to shut down your machine when the sysprep process has completed. This process can take some
time. You can monitor the machine in the Windows Azure Management Portal by watching for the machine to show as
Stopped.
17.1.7. Capture Image
This is the second of two off-box tasks within the scope of creating the SharePoint image. The script consists of the
following elements:


Variable Block – This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
Image Capture – This section (starting with the comment “Save the image…”) contains the command that will
capture the image.
To finalize the creation of the SharePoint server image, run the following Windows Azure PowerShell command (use the
variable/subscription block with the storage account defined).
# Variable Block...
$vmName = "BIPaper-SP"
$newImageName = "BIPaper-SharePoint"
$newImageLabel = "BI Paper SharePoint"
# Save the image...
Save-AzureVMImage `
-Name $vmName `
-NewImageName $newImageName `
-ServiceName $cloudServiceName `
-NewImageLabel $newImageLabel
Validation
There are two ways to verify that the virtual machine image was created:
Page 58 of 86

Portal – In the Windows Azure Management Portal, click Virtual Machines. In the virtual machines screen, click
Images and then verify that the virtual machine image exists (you might need to refresh the page).

PowerShell – Run the following Windows PowerShell command (include the same variable script block used to
run the command above). It should return the value True.
((Get-AzureVMImage -ImageName "BIPaper-SharePoint") -ne $NULL)
17.2. First SharePoint Server
The SharePoint server that we will be creating will serve as our first application tier server, and it will also host the
Central Administration web application for the farm.
Although it would be possible to build this on your own, we suggest that you either use the scripts in this section or
provision the VM from the SharePoint image created and then run the PowerPivot for SharePoint 2013 configuration
tool to complete the configuration (followed by the Reporting Services installation).
Note: This step requires installation media for SQL Server 2012 (to install Reporting Services). Place the information in
the following directories on the VM:


D:\SQL Server 2012\ – This should be the contents of the SQL Server installation media (use the media with SP1
slipstreamed). Do not just put the .iso file in this directory—it needs to be the contents of the media extracted.
D:\SQL Server 2012 CU\ – This should be the .exe file that you would run to apply the CU. The CUs are delivered
as executable .zip files, the contents of which are what we are looking for in this directory.
17.2.1. Provision VM
This is the only off-box task within the scope of creating the first SharePoint application-tier server. All other scripts are
run in a remote desktop session on the machine. The script consists of the following elements:


Variable Block – This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
VM Creation – This section (starting with the comment “Creating the virtual machine…”) consists of the
following Windows Azure commands:
o New-AzureVMConfig – This command begins the definition of the virtual machine. It sets the name, size,
image, .vhd location and label, and availability set.
o Add-AzureProvisioningConfig – This command determines how Windows Azure should provision the VM
defined in the last command. It tells Windows Azure that this will be a Windows machine, that
automatic updates should be disabled (you can turn this back on if you want), that there should not be
endpoints for RDP or Remote Windows PowerShell, and what the administrator user and password
should be. Additionally, this command provides the information necessary to automatically join the
machine to our domain.
o Set-AzureSubnet – This command defines what subnet the virtual machine should be deployed into.
o New-AzureVM – This command does the work of creating the virtual machine that was defined in the
earlier commands. In addition to the information gathered from the earlier commands, it defines the
cloud service that should be used. The script loops until creation of the VM is complete and writes a
status to the screen every 15 seconds.
Page 59 of 86
To create the first SharePoint server, run the following Windows Azure PowerShell command (use the
variable/subscription block with the storage account defined).
# Get the name for the VM...
$vmName = "BIPaper-App1"
$vmImageName = "BIPaper-SharePoint"
# Get the admin user name for the VM...
$vmAdminUserName = Read-Host -Prompt "Server Administrator User Name"
# Ask for the password that should be used for the server and convert it to a format usable by the
commands...
$vmAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Server Administrator Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($vmAdminPasswordSecure)
$vmAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
# Get the domain admin user name...
$domainAdminUserName = Read-Host -Prompt "Domain Administrator User Name"
# Ask for the domain admin password and convert it to a format usable by the commands...
$domainAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Domain Administrator Password"
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($domainAdminPasswordSecure)
$domainAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Set the location of the .vhd files...
$storageAccountContainer = "https://" + $storageAccountName + ".blob.core.windows.net/vhds/"
$vmVHDLocation = $storageAccountContainer + $vmName + ".vhd"
# Create the virtual machine...
Write-Host "Creating the VM..."
New-AzureVMConfig `
-Name $vmName `
-InstanceSize ExtraLarge `
-ImageName $vmImageName `
-MediaLocation $vmVHDLocation `
-DiskLabel "OS" `
-AvailabilitySetName "AppAvailabilitySet" |
Add-AzureProvisioningConfig `
-WindowsDomain `
-DisableAutomaticUpdates `
-DisableWinRMHttps `
-NoRDPEndpoint `
-Domain $domainName `
-JoinDomain $domainNameFQ `
-DomainPassword $domainAdminPassword `
-DomainUserName $domainAdminUserName `
-AdminUsername $vmAdminUserName `
-Password $vmAdminPassword |
Set-AzureSubnet `
-SubnetNames "AppNet" |
New-AzureVM `
-ServiceName $cloudServiceName
# Loop until Satus = ReadyRole...
Write-Host "`tWaiting for Provisioning to Complete..."
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
While ($VMStatus.InstanceStatus -ne "ReadyRole")
{
write-host "`t`tWaiting...Current Status = " $VMStatus.InstanceStatus
Start-Sleep -Seconds 15
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
}
Validation
There are two ways to verify that the virtual machine was created:

Portal – In the Windows Azure Management Portal, click Virtual Machines and then verify that the virtual
machine exists (you might need to refresh the page).
Page 60 of 86

Windows PowerShell – Run the following Windows PowerShell command (include the same variable script
block used to run the command above). It should return the value True.
((Get-AzureVM -name "BIPaper-App1" -ServiceName $cloudServiceName) -ne $NULL)
17.2.2. Create New Farm
This on-box script creates the SharePoint farm. You are prompted for the password for the SP_Farm service account and
for the password that you want to use for the farm passphrase. The script installs the databases onto the server BIPaperDB1 and it uses the SP_Farm service account—if you have changed either of these values while creating this
environment you will need to adjust the variable block of the script.
Note: These scripts perform the exact same actions that would be performed by running the PowerPivot for SharePoint
2013 configuration tool. If you are not comfortable running the scripts in this format, you can log in to the server and
then run the PowerPivot for SharePoint 2013 configuration tool to create the farm—it will do exactly the same thing
that we do here. If you choose to build the farm through the configuration tool, skip to the “Configure Alternate Access
Mappings” script.
Note: Individual scripts are not verified in this section. The entire section is verified after the “Configure Excel Services”
section.
Run the following script in Windows PowerShell on the target machine using the on-box variable block defined earlier in
the document.
# Variable Block...
$caPort = 8080
# Get passwords...
$servicePasswordSecure = Read-Host -AsSecureString -Prompt "Service Account Password
($farmServiceAccount)"
$farmPassphraseSecure = Read-Host -AsSecureString -Prompt "Farm Passphrase"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($servicePasswordSecure)
$servicePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($farmPassphraseSecure)
$farmPassphrase = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Configure farm...
C:
CD "\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\BIN\"
.\psconfig.exe `
-cmd configdb -create -server "$dbServer" -database "SharePoint_Config" -user
"$domainName\$farmServiceAccount" -password $servicePassword -passphrase $farmPassphrase admincontentdatabase "SharePoint_Admin" `
-cmd helpcollections -installall `
-cmd secureresources `
-cmd services -install `
-cmd installfeatures `
-cmd adminvs -provision -port $caPort -windowsauthprovider onlyusentlm `
-cmd applicationcontent -install `
-cmd quiet
17.2.3. Add PowerPivot Solutions
To add the PowerPivot solution to the farm, run the following script on the target server (no variable block is required).
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
Page 61 of 86
Add-SPSolution -LiteralPath 'C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\powerpivotfarmsolution.wsp'
Add-SPSolution -LiteralPath 'C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\PowerPivotFarm14Solution.wsp'
Add-SPSolution -LiteralPath 'C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\powerpivotwebapplicationsolution.ws
p'
DeployFarmSolution $false
DeployWebAppSolutionToCentralAdmin $false
Important: Close and reopen the PowerShell window before running the next script. The PowerPivot cmdlets were
installed with this step and the PowerShell environment cannot use the PowerPivot cmdlets until the PowerShell
window is restarted.
17.2.4. Install PowerPivot Features
To install the PowerPivot feature, run the following script on the target server (no variable block is required).
Add-PSSnapin Microsoft.SharePoint.PowerShell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
Install-SPFeature -path PowerPivotFarm -Force
Install-SPFeature -path PowerPivotFarm -Force -CompatibilityLevel 14
Install-SPFeature -path PowerPivotCA -Force
InstallSiteCollectionFeatures
17.2.5. Configure Service Instance
To configure the PowerPivot service instance, run the following script on the target server (no variable block is required).
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
New-PowerPivotSystemServiceInstance -Provision:$true
17.2.6. Create PowerPivot Service Application
To create the PowerPivot Service application, run the following script on the target server using the on-box variable
block defined earlier in the document.
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
New-PowerPivotServiceApplication `
-ServiceApplicationName 'Default PowerPivot Service Application' `
-DatabaseServerName $dbServer `
-DatabaseName 'DefaultPowerPivotServiceApplicationDB' `
-AddToDefaultProxyGroup:$true
Set-PowerPivotSystemService -Confirm:$false
17.2.7. Create Default Web Application
To create the default SharePoint web application, run the following script on the target server using the on-box variable
block defined earlier in the document.
Add-PSSnapin Microsoft.SharePoint.Powershell
Page 62 of 86
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
$serviceAccountPasswordSecure = Read-Host -AsSecureString -Prompt "Service Account Password
($farmServiceAccount)"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($serviceAccountPasswordSecure)
$serviceAccountPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
CreateWebApplication "SharePoint - 80" "http://$cloudServiceName.cloudapp.net" "Default Application
Pool" "$domainName\$farmServiceAccount" $serviceAccountPassword $dbServer "DefaultWebApplicationDB"
17.2.8. Deploy Web Application Solution
To deploy the web application solution, run the following script on the target server using the on-box variable block
defined earlier in the document.
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
DeployWebAppSolution "http://$cloudServiceName.cloudapp.net" 2047 $false
17.2.9. Create Site Collection
To create the site collection, run the following script on the target server using the on-box variable block defined earlier
in the document.
# Variable block...
$domainAdminAccount = Read-Host -Prompt "Domain Administrator Account Name"
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
New-SPSite `
-Url "http://$cloudServiceName.cloudapp.net" `
-OwnerAlias "$domainName\$farmServiceAccount" `
-SecondaryOwnerAlias "$domainName\$domainAdminAccount" `
-Template 'PowerPivot#0' `
-Name 'PowerPivot Site'
17.2.10. Activate PowerPivot Feature
To active the PowerPivot feature in the site that was just created, run the following script on the target server using the
on-box variable block defined earlier in the document.
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
EnableSiteFeatures "http://$cloudServiceName.cloudapp.net" $true
17.2.11. Start the Claims to Windows Token Service
To start the Claims to Windows Token Service on the server, run the following script on the target server (no variable
block is required).
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
StartService "Microsoft.SharePoint.Administration.Claims.SPWindowsTokenServiceInstance"
Page 63 of 86
17.2.12. Configure Secure Store Service
To configure the Secure Store service, run the following script on the target server using the on-box variable block
defined earlier in the document (you will be prompted for the farm service account password and for a password that
will be used for your secure store master key).
# Variable block...
$password = Read-Host -AsSecureString -Prompt "Farm Account Password ($farmServiceAccount)"
$secureStorePassword = Read-Host -AsSecureString -Prompt "Secure Store Password"
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
StartSecureStoreService
CreateSecureStoreApplicationService $dbServer "Secure Store Service"
CreateSecureStoreApplicationServiceProxy "Secure Store Service" "Secure Store Proxy"
UpdateSecureStoreMasterKey "Secure Store Proxy" $secureStorePassword
CreateUnattendedAccountForDataRefresh "http://$cloudServiceName.cloudapp.net"
"PowerPivotUnattendedAccount" "PowerPivot Unattended Account for Data Refresh"
"$domainName\$farmServiceAccount" $password
Configure Excel Services
To configure Excel Services for the farm, run the following script on the target server (no variable block is required). If
the server names you used for the PowerPivot servers are different from the default, you will need to change them in
this script.
# Variable block...
$firstPowerPivotServer = "BIPaper-PP1\PowerPivot"
$secondPowerPivotServer = "BIPaper-PP2\PowerPivot"
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
StartService "Microsoft.Office.Excel.Server.MossHost.ExcelServerWebServiceInstance"
New-SPExcelServiceApplication -name 'ExcelServiceApp1' -Default -ApplicationPool 'SharePoint Web
Services System' | Get-SPExcelServiceApplication | Set-SPExcelServiceApplication | iisreset
Set-SPExcelFileLocation -ExternalDataAllowed 2 -WorkbookSizeMax 200 -WarnOnDataRefresh:$false ExcelServiceApplication 'ExcelServiceApp1' -identity 'http://'
$excelServiceApp = Get-SPExcelServiceApplication | where {$_.Name -eq "ExcelServiceApp1"}
New-SPExcelBIServer -ServerId $firstPowerPivotServer -ExcelServiceApplication $excelServiceApp
New-SPExcelBIServer -ServerId $secondPowerPivotServer -ExcelServiceApplication $excelServiceApp
SetECSUsageTracker 'ExcelServiceApp1'
Note: In a production environment, you should use separate app pools for Excel Services and Secure Store for security
isolation.
Validation
To verify that the SharePoint and PowerPivot configuration worked properly:
1) Log in to the server.
Page 64 of 86
2) Start the PowerPivot for SharePoint 2013 Configuration tool.
3) In the PowerPivot Configuration Tool dialog box, click Configure or Repair PowerPivot for SharePoint, and then
click OK.
4) Verify that no tasks appear in the left-hand tree view and that the message “No further action is required. This
step is either already verified or configured” is displayed at the bottom of the right-hand side of the window.
17.2.13. Configure Alternate Access Mappings
To create the alternate access mappings and self-signed SSL Certificate, run the following script on the target server
using the variable block defined earlier in the document (you will be prompted for a password to use for the certificate
output file).
# Variable block...
$certPassword = Read-Host -AsSecureString -Prompt "Certificate Password"
Add-PSSnapin Microsoft.SharePoint.Powershell
# Create Alternate Access Mapping...
New-SPAlternateURL `
-Url "https://$cloudServiceName.cloudapp.net" `
-WebApplication "http://$cloudServiceName.cloudapp.net" `
-Zone "Extranet"
New-SPAlternateURL `
-Url "http://$env:COMPUTERNAME" `
-WebApplication "http://$cloudServiceName.cloudapp.net" `
-Zone "Intranet"
New-SPExcelFileLocation `
-Address "https://" `
-ExcelServiceApplication "ExcelServiceApp1" `
-IncludeChildren `
-ExternalDataAllowed "DclAndEmbedded" `
-WarnOnDataRefresh:$false
# Make a certificate...
if ((Test-Path "C:\Temp") -eq $false)
{
New-Item -Path "C:\Temp" -ItemType directory
}
cd "\Program Files\Microsoft Office Servers\15.0\Tools"
.\makecert -sky exchange -r -n "CN=$cloudServiceName.cloudapp.net" -pe -a sha1 -len 2048 -eku
1.3.6.1.5.5.7.3.1 -ss My -sr LocalMachine
$cert = Get-ChildItem cert:\LocalMachine\My | Where {$_.Subject -eq
"CN=$cloudServiceName.cloudapp.net"}
Get-ChildItem -Path cert:\LocalMachine\my | where {$_.Subject -eq
"CN=$cloudServiceName.cloudapp.net"} | Export-PfxCertificate -FilePath
"C:\Temp\$cloudServiceName.cloudapp.net.pfx" -Password $certPassword
# Create a new binding for the SharePoint site...
New-WebBinding -Name "SharePoint - 80" -Protocol "https" -Port 443 -IPAddress "*"
# Bind the certificate
CD IIS:\SslBindings
$cert | new-item 0.0.0.0!443
Validation
Follow these steps to validate this task:
Page 65 of 86
1) Verify alternate access mappings. Log in to the server, start SharePoint 2013 Central Administration (you will
need to disable IE ESC before this step if you haven’t already done it), and then click Application Management.
2) Click Configure alternate access mappings under Web Applications, and then to the right of alternate Access
Mapping Collection, click Show All.
3) Click Change Alternate Access Mapping Collection.
4) In the Select an Alternate Access Mapping Collection dialog box, click SharePoint – 80.
5) Verify that there are three URLs:
 http://<cloudservice>.cloudapp.net (<cloudservice> will be your unique cloud service name)
 http://bipaper-app1 (will be different if you gave your SharePoint server a different name)
 https://<cloudservice>.cloudapp.net (<cloudservice> will be your unique cloud service name)
6) Verify the Excel Services file location. Log in to the server, start SharePoint 2013 Central Administration, click
Application Management, and then under Service Applications, click Manage service applications.
7) Click ExcelServiceApp1 (there will be two listed; click the one that is left-justified), click Trusted File Locations,
and then verify that both http:// and https:// are listed.
8) Verify SSL binding. Log in to the server, and then start Internet Information Services (IIS) Manager.
9) In the left-hand tree view, expand the server name, expand Sites, right-click SharePoint – 80, and then click Edit
Bindings.
10) In the Site Bindings dialog box, select https and then click Edit. Verify that the SSL certificate is the name of your
cloud service’s public URL (<cloudservice>.cloudapp.net).
11) Verify the certificate file export. Log in to the server, open Windows Explorer, and then navigate to C:\Temp.
Verify that the file <cloudservice>.cloudapp.net.pfx exists.
17.2.14. Install Reporting Services
This step is divided into four parts:
1) Install Reporting Services Bits – Installs the SQL Server Reporting Services binaries, but does not do any
configuration.
2) Enable Reporting Services – Installs the SQL Server Reporting Services binaries into SharePoint.
3) Create Reporting Services Shared Service Application – Creates the SharePoint shared service application that
will allow users to interact with reporting services.
4) Grant Reporting Services permissions on the site content database – Gives the Reporting Services service
account rights to access the SharePoint content database for our site collection.
17.2.15. Install Reporting Services Bits
This step installs the SQL Server Reporting Services binaries onto the SharePoint application tier. This step needs to be
run only on servers that will act as report servers—Web Front End servers do not need to have these binaries installed.
Note: This step requires installation media for SQL Server 2012 (to install Reporting Services). Place the information in
the following directories on the VM:


D:\SQL Server 2012\ – This should be the contents of the SQL Server installation media (use the media with SP1
slipstreamed). Do not just put the .iso file in this directory—it needs to be the contents of the media extracted.
D:\SQL Server 2012 CU\ – This should be the .exe file that you would run to apply the CU. The CUs are delivered
as executable .zip files, the contents of which are what we are looking for in this directory.
To install SQL Server Reporting Services, run the following script on the target server (no variable block is required, but
you will be prompted for your SQL Server license key).
# Get the SQL Server license key...
$sqlpid = Read-Host -Prompt "SQL Server License Key"
Page 66 of 86
# Install SQL Server...
D:
CD "\SQL Server 2012"
.\setup.exe `
/Action=Install `
/PID="$sqlpid" `
/IACCEPTSQLSERVERLICENSETERMS `
/ENU `
/UpdateEnabled=1 `
/UpdateSource="D:\SQL Server 2012 CU" `
/ErrorReporting=0 `
/Features=RS_SHP `
/IndicateProgress `
/QS
You now need to restart the server.
Validation
To verify that Reporting Services was installed properly:
1) Log in to the server.
2) Open Windows Explorer.
3) Navigate to “C:\Program Files\Microsoft SQL Server\110\Setup Bootstrap\Log” and open the “Summary.txt”
file.
4) Verify that the Final result is Passed but reboot required, see logs for details.
5) Verify that the Exit code (Decimal) is 3010.
17.2.16. Enable Reporting Services
To enable the Reporting Services bits within SharePoint, run the following script on the target server (no variable block is
required).
Add-PSSnapin Microsoft.SharePoint.Powershell
$RS = Get-SPServiceInstance -Server $env:COMPUTERNAME | Where {$_.TypeName -eq "SQL Server
Reporting Services Service"}
if ($RS -eq $NULL)
{
Install-SPRSService
Install-SPRSServiceProxy
}
$RS = Get-SPServiceInstance -Server $env:COMPUTERNAME | Where {$_.TypeName -eq "SQL Server
Reporting Services Service"}
Start-SPServiceInstance -Identity $RS.Id.ToString()
Validation
To verify that Reporting Services was successfully enabled:
1) Log in to the server.
2) Open Windows PowerShell.
3) Run the command Add-PSSnapin Microsoft.SharePoint.Powershell to import the SharePoint PowerShell
cmdlets.
4) Run the following script (it should return the value True).
((Get-SPServiceInstance | where {$_.TypeName -eq "SQL Server Reporting Services
Service"}).Status -eq "Online")
Page 67 of 86
17.2.17. Create Reporting Services Shared Service Application
To create the Reporting Services Shared Service Application, run the following script on the target server using the
variable block defined earlier in the document (you will be prompted for the password for the Reporting Services service
account).
Add-PSSnapin Microsoft.SharePoint.Powershell
# Get the Reporting Services Account Credentials...
$cred = Get-Credential "$domainName\$reportingServiceAccount" # TODO: Type password when
prompted...
# Create a managed service account...
New-SPManagedAccount -Credential $cred
# Create a new application pool for Reporting Services...
New-SPServiceApplicationPool -Name "Reporting Services" -Account
"$domainName\$reportingServiceAccount"
$appPool = Get-SPServiceApplicationPool "Reporting Services"
# Create the Reporting Services Service Application...
$rsService = New-SPRSServiceApplication -Name "Reporting Services Application" -ApplicationPool
$appPool -DatabaseName "Reporting_Services_Application" -DatabaseServer "$dbServer"
# Create the Reporting Services Service Application Proxy...
$rsServiceProxy = New-SPRSServiceApplicationProxy -Name "Reporting Services Application Proxy" ServiceApplication $rsService
# Associate the Reporting Services Service Application Proxy with the default web site...
Get-SPServiceApplicationProxyGroup -default | Add-SPServiceApplicationProxyGroupMember -Member
$rsServiceProxy
Validation
To verify that the Reporting Services application was successfully created:
1) Log in to the server.
2) Open Windows PowerShell.
3) Run the command Add-PSSnapin Microsoft.SharePoint.Powershell to import the SharePoint PowerShell
cmdlets.
4) Run the following script (it should return the value True).
((Get-SPServiceApplication | where {$_.DisplayName -eq "Reporting Services Application" -and
$_.TypeName -eq "SQL Server Reporting Services Service Application"}) -ne $NULL)
17.2.18. Grant Reporting Services permissions
To grant the Reporting Services application permissions on the content database that was created, run the following
script on the target server using the variable block defined earlier in the document.
Add-PSSnapin Microsoft.SharePoint.Powershell
$appPool = Get-SPServiceApplicationPool "Reporting Services"
$webApp = Get-SPWebApplication "http://$cloudServiceName.cloudapp.net"
$appPoolAccountName = $appPool.ProcessAccount.LookupName()
$webApp.GrantAccessToProcessIdentity($appPoolAccountName)
Validation
To verify that the permissions have been set on the content database:
1)
2)
3)
4)
Log in to the database server.
Open SQL Server Management Studio, and then connect to the database server.
In the left-hand tree view, expand the Security node.
In the left-hand tree view, expand the Logins node.
Page 68 of 86
5) In the left-hand tree view, double-click BIPaper\SQL_Reporting (or the name of the Reporting Services service
account if you changed it).
6) In the Login Properties dialog box, click User Mapping, and then verify that rights have been granted to the
DefaultWebApplicationDB database (it should be a member of the SPDataAccess role).
17.3.
Section Validation
At this point, you have a fully functional SharePoint site with the BI features enabled. You can access the site only if you
are logged into a server on the virtual network (we haven’t defined any public Web Front Ends yet). If you want to take
the site out for a test, log in to one of the servers in the virtual network, open Internet Explorer, and then navigate to
http://bipaper-app1 (or the name that you gave to the server if you did not use the default naming).
Note: There is a chance that the first time you access the site you will be presented with an unhandled exception. If this
happens, refresh the page and everything should be fine.
To Overview of the deployment steps
Page 69 of 86
18.
Step 6: Configure AlwaysOn Availability Groups
Even though we have built out seven servers, only two out of the four tiers that we have deployed have high availability
(HA) configured:




Domain controllers – highly available
Database servers – HA ready (need cluster)
PowerPivot servers – highly available
SharePoint App-Tier – no HA (single server)
In this section, we will go through the steps of configuring HA for our database servers and letting SharePoint know how
to take advantage of that configuration.
At the end of this section we will have accomplished the following:



Windows Failover Cluster
o Cluster name – BIPaper-DB
o Cluster nodes
 BIPaper-DB1
 BIPaper-DB2
o Quorum
 Type – Node and File Share Majority
 Quorum file share - \\BIPaper-DC2\Quorum
AlwaysOn Availability Groups enabled on database servers (BIPaper-DB1 and BIPaper-DB2)
Availability Group
o Name – SharePoint
o Primary server – BIPaper-DB1
o Secondary server – BIPaper-DB2
o Replicas are not readable
o Databases – all user databases created during SharePoint configuration
Note: Because listeners are not currently supported in Windows Azure Virtual Machines, we will use the database
mirroring-style connection strings for SharePoint (we will set the FailoverPartner property for the secondary replica).
This is why our replicas cannot be readable.
If you feel comfortable creating this environment on your own, you can do so and then skip to the “Deploy SharePoint
Web Front End Servers” section.
18.1.
Create Cluster
The following script verifys and creates a Windows failover cluster. It performs three tasks (Verify Cluster, Create
Cluster, and Set Quorum). It should be run from the primary database server (BIPaper-DB1, if you haven’t changed it)
using the on-box variable block defined earlier in the document.
# Validate the Cluster Nodes...
Test-Cluster -Node $dbServer, $dbServer2
# Create the Cluster...
New-Cluster -Name $clusterName -Node $dbServer, $dbServer2
# Set the cluster quorum...
Set-ClusterQuorum -NodeAndFileShareMajority "\\$quorumServerName\Quorum"
Page 70 of 86
18.1.1. Validation
There are two parts to validating this step: the validation report and Failover Cluster Manager.
Validation Report
1) In the output of the Windows PowerShell command, find “Test report file path”.
2) If you don’t have the path, check the AppData\Local\Temp\2\ path under the user that ran the Windows
PowerShell script (the file should be a .mht file, the file name should start with “Validation Report”, and the file
should contain the date and time that validation was run).
3) Open the file. Both nodes should show up in the report as Validated and your results should either be Success or
Warning.
Failover Cluster Manager
1)
2)
3)
4)
Log into the target machine.
Open Failover Cluster Manager.
In the left-hand tree view, click the name of the cluster.
In the center content, verify that the Quorum Configuration is Node and File Share Majority (\\BIPaperDC2\Quorum) (or the name of the quorum server you used).
5) In the left-hand tree view, expand the name of the cluster.
6) In the left-hand tree view, click Nodes. In the center content well, you should see both of your database servers
listed as cluster nodes.
18.2.
Enable AlwaysOn Availability Groups
The following scripts enable the AlwaysOn Availability Groups feature for the SQL Server instances. There is one script
for each database server.
These scripts assume that you are using the default service accounts created in this paper. If you are not, you will need
to adjust the service account variable at the top of each script.
Note: This process restarts SQL Server and SQL Server Agent on the target machine.
To run these scripts, you will need to set your execution policy to something other than the default (for this paper, we
used RemoteSigned).
To enable AlwaysOn Availability Groups on your first database server, run the following script on the first database
server (this script does not require the variable block defined earlier in the paper).
# Variable Block...
$otherServiceAccount = "DB2_SQL_Engine"
Import-Module "sqlps" -DisableNameChecking
# Enable the Feature...
$computerName = $env:COMPUTERNAME
Enable-SqlAlwaysOn -Path SQLSERVER:\SQL\$computerName\Default -Force
Start-Service -Name "SQL Server Agent (MSSQLSERVER)"
# Enable the Endpoint...
$endpoint = New-SqlHadrEndpoint MirrorEndpoint -Port 5022 -Path
SQLSERVER:\SQL\$computerName\Default
Set-SqlHadrEndpoint -InputObject $endpoint -State "Started"
# Grant Permissions...
Invoke-SqlCmd -Query "CREATE LOGIN [$env:USERDOMAIN\$otherServiceAccount] FROM WINDOWS" ServerInstance $computerName
Invoke-SqlCmd -Query "GRANT CONNECT ON ENDPOINT::[MirrorEndpoint] TO
[$env:USERDOMAIN\$otherServiceAccount]" -ServerInstance $computerName
Page 71 of 86
To enable AlwaysOn Availability Groups on your second database server, run the following script on the second
database server (this script does not require the variable block defined earlier in the paper).
# Variable Block...
$otherServiceAccount = "DB1_SQL_Engine"
Import-Module "sqlps" -DisableNameChecking
# Enable the Feature...
$computerName = $env:COMPUTERNAME
Enable-SqlAlwaysOn -Path SQLSERVER:\SQL\$computerName\Default -Force
Start-Service -Name "SQL Server Agent (MSSQLSERVER)"
# Enable the Endpoint...
$endpoint = New-SqlHadrEndpoint MirrorEndpoint -Port 5022 -Path
SQLSERVER:\SQL\$computerName\Default
Set-SqlHadrEndpoint -InputObject $endpoint -State "Started"
# Grant Permissions...
Invoke-SqlCmd -Query "CREATE LOGIN [$env:USERDOMAIN\$otherServiceAccount] FROM WINDOWS" ServerInstance $computerName
Invoke-SqlCmd -Query "GRANT CONNECT ON ENDPOINT::[MirrorEndpoint] TO
[$env:USERDOMAIN\$otherServiceAccount]" -ServerInstance $computerName
18.2.1. Validation
Perform these validation steps on each database server:
1) Log in to the server.
2) Start SQL Server Configuration Manager. In the left-hand tree view, click SQL Server Services.
3) In the right-hand list view, double-click SQL Server (MSSQLSERVER). In the Properties dialog box, click
AlwaysOn High Availability, and then verify that the cluster name is populated and the Enable AlwaysOn
Availability Groups check box is selected.
4) Start SQL Server Management Studio, and then connect to the local server instance.
5) In the left-hand tree view, expand Server Objects, expand Endpoints, and then expand Database Mirroring.
6) Verify that the endpoint MirrorEndpoint exists.
7) In the left-hand tree view, expand Security, expand Logins, and then double-click the name of the service
account that is running the other database server.
8) In the Login Properties dialog box, click Securables, click MirrorEndpoint, and then verify that Grant
permissions have been granted for Connect.
18.3.
Create Availability Group
This script configures the availability group between the two database servers. It performs the following tasks:





Sets the appropriate recovery model (full) for WSS_Logging database
Performs full and log backups of each database on the primary server
Restores each database and log backup onto the secondary server
Creates the availability group and joins the secondary server and databases to it
Synchronizes logins to secondary server
To perform these tasks, run the following script on the primary database server using the on-box variable block defined
earlier in this document.
Import-Module "sqlps" -DisableNameChecking
SQLServer:
Page 72 of 86
CD "\sql\$dbServer\default\databases"
# Change WSS_Logging to full recovery model...
Invoke-Sqlcmd -Query "ALTER DATABASE [WSS_Logging] SET RECOVERY FULL WITH NO_WAIT" -ServerInstance
$dbServer
# Backup Databases and Logs...
ls | foreach-object { Backup-SqlDatabase -Database $_.name -ServerInstance $dbServer -BackupAction
Database -BackupFile ("\\$quorumServerName\quorum\" + $_.name.ToString() + ".bak") CompressionOption On }
ls | foreach-object { Backup-SqlDatabase -Database $_.name -ServerInstance $dbServer -BackupAction
Log -BackupFile ("\\$quorumServerName\quorum\" + $_.name + ".log") -CompressionOption On }
# Restore Databases and Logs...
ls | foreach-object { Restore-SqlDatabase -Database $_.name -ServerInstance $dbServer2 -BackupFile
("\\$quorumServerName\quorum\" + $_.name + ".bak") -NoRecovery -RestoreAction Database }
ls | foreach-object { Restore-SqlDatabase -Database $_.name -ServerInstance $dbServer2 -BackupFile
("\\$quorumServerName\quorum\" + $_.name + ".log") -NoRecovery -RestoreAction Log }
# Create primary replica template...
$primaryReplica = New-SqlAvailabilityReplica -AvailabilityMode "SynchronousCommit" -EndpointUrl
"TCP://$dbServer`:5022" -FailoverMode "Automatic" -Name $dbServer -AsTemplate -Version 11
# Create secondary replica template...
$secondaryReplica = New-SqlAvailabilityReplica -AvailabilityMode "SynchronousCommit" -EndpointUrl
"TCP://$dbServer2`:5022" -FailoverMode "Automatic" -Name $dbServer2 -AsTemplate -Version 11
# Create Availability Group...
New-SqlAvailabilityGroup -Name "SharePoint" -Path "SQLSERVER:\SQL\$dbServer\Default" AvailabilityReplica @($primaryReplica, $secondaryReplica)
ls | foreach-object { Add-SQLAvailabilityDatabase -Path
"SQLSERVER:\SQL\$dbServer\Default\AvailabilityGroups\SharePoint" -Database $_.name }
# Join Secondary to Availability Group...
Join-SqlAvailabilityGroup -Path "SQLSERVER:\SQL\$dbServer2\Default" -Name "SharePoint"
# Join Secondary Databases to Availability Group...
ls | foreach-object { Add-SQLAvailabilityDatabase -Path
"SQLSERVER:\SQL\$dbServer2\Default\AvailabilityGroups\SharePoint" -Database $_.name }
# Synchronize Logins...
Invoke-Sqlcmd -Query "CREATE LOGIN [$domainName\$farmServiceAccount] FROM WINDOWS WITH
DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]" -ServerInstance $dbServer2
Invoke-Sqlcmd -Query "ALTER SERVER ROLE [securityadmin] ADD MEMBER
[$domainName\$farmServiceAccount]" -ServerInstance $dbServer2
Invoke-Sqlcmd -Query "ALTER SERVER ROLE [dbcreator] ADD MEMBER [$domainName\$farmServiceAccount]" ServerInstance $dbServer2
Invoke-Sqlcmd -Query "CREATE LOGIN [$domainName\$reportingServiceAccount] FROM WINDOWS WITH
DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]" -ServerInstance $dbServer2
18.3.1. Validation
To verify this step:
1)
2)
3)
4)
5)
6)
7)
8)
Log in to the primary database server.
Open SQL Server Management Studio.
Open connections to both database servers.
Verify that all of the user databases on the primary server are also on the secondary server.
In the left-hand tree view, expand the AlwaysOn High Availability node of the primary server.
In the left-hand tree view, expand the Availability Groups node, and then expand SharePoint (Primary).
In the Availability Replicas node, verify that both servers exist.
In the Availability Databases node, verify that all user databases exist.
Page 73 of 86
18.4.
Enable High Availability in SharePoint
In this step, we will tell the SharePoint server how to communicate with our highly available databases. The
environment does not use the Session State Service.
To enable high availability in SharePoint, run the following Windows PowerShell script on the SharePoint application
server using the on-box variable block defined earlier in this document.
Add-PSSnapin Microsoft.SharePoint.Powershell
get-spdatabase | where { $_.FailoverServer -eq $null } | ForEach-Object {
$_.AddFailoverServiceInstance($dbServer2) ; $_.Update() }
18.4.1. Validation
To verify that this step worked, log into the SharePoint server and then run the following Windows PowerShell
command (no variable block is required). It should return an empty list.
Add-PSSnapin Microsoft.SharePoint.Powershell
get-spdatabase | where { $_.FailoverServer -eq $null }
At this point your SharePoint farm is configured with highly available databases.
To Overview of the deployment steps
Page 74 of 86
19.
Step 7: Deploy SharePoint Web Front End Servers
In this section we will create the SharePoint Web Front End servers (Bipaper-WFE1 and BiPaper-WFE2). We will use the
SharePoint image that was created earlier in this paper as a basis for the VM so that we can skip the process of installing
all of the software.
At the end of this section, you will have an environment that looks like this:


First SharePoint Web Front End
o Server Name – BIPaper-WFE1
o Storage Account – <your globally unique name>
o Domain/Forest Name – BIPaper.local
o Network Subnet – WebNet
o Availability Set – WebAvailabilitySet
o Load Balanced Endpoint
 Name – https
 Public Port – 443
 Private Port – 443
o Joined to SharePoint Farm
o PowerPivot Solutions Deployed
Second SharePoint Web Front End
o Server Name – BIPaper-WFE2
o Storage Account – <your globally unique name>
o Domain/Forest Name – BIPaper.local
o Network Subnet – WebNet
o Availability Set – WebAvailabilitySet
o Load Balanced Endpoint
 Name – https
 Public Port – 443
 Private Port – 443
o Joined to SharePoint Farm
o PowerPivot Solutions Deployed
If you feel comfortable creating this environment on your own, you can do so and then skip to the “Deploy Additional
SharePoint Application/Central Administration Servers” section.
19.1.
Provision VM
This is the only off-box task within the scope of creating the first SharePoint Web Front End server. All other
scripts run in a remote desktop session on the machine. The script consists of the following elements:


Variable Block – This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
VM Creation – This section (starting with the comment “Creating the virtual machine…”) consists of the
following Windows Azure commands:
o New-AzureVMConfig – This command begins the definition of the virtual machine. It sets the name, size,
image, .vhd location and label, and availability set.
o Add-AzureProvisioningConfig – This command determines how Windows Azure should provision the VM
defined in the last command. It tells Windows Azure that this will be a Windows machine, that
automatic updates should be disabled (you can turn this back on if you want), that there should not be
endpoints for RDP or Remote Windows PowerShell, and what the administrator user and password
Page 75 of 86
o
o
o
should be. Additionally, this command provides the information necessary to automatically join the
machine to our domain.
Set-AzureSubnet – This command defines what subnet the virtual machine should be deployed into.
Add-AzureEndpoint – This command creates the load-balanced endpoint that will be the public gateway
to this VM.
New-AzureVM – This command does the work of creating the virtual machine that was defined in the
earlier commands. In addition to the information gathered from the earlier commands, it defines the
cloud service that should be used. The script loops until creation of the VM is complete and writes a
status to the screen every 15 seconds.
To create the first SharePoint Web Front End server, run the following Windows Azure PowerShell command (use
the variable/subscription block with the storage account defined).
# Get the name for the VM...
$vmName = "BIPaper-WFE1"
$vmImageName = "BIPaper-SharePoint"
# Get the admin user name for the VM...
$vmAdminUserName = Read-Host -Prompt "Server Administrator User Name"
# Ask for the password that should be used for the server and convert it to a format usable by the
commands...
$vmAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Server Administrator Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($vmAdminPasswordSecure)
$vmAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
# Get the domain admin user name...
$domainAdminUserName = Read-Host -Prompt "Domain Administrator User Name"
# Ask for the domain admin password and convert it to a format usable by the commands...
$domainAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Domain Administrator Password"
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($domainAdminPasswordSecure)
$domainAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Set the location of the .vhd files...
$storageAccountContainer = "https://" + $storageAccountName + ".blob.core.windows.net/vhds/"
$vmVHDLocation = $storageAccountContainer + $vmName + ".vhd"
# Create the virtual machine...
Write-Host "Creating the VM..."
New-AzureVMConfig `
-Name $vmName `
-InstanceSize ExtraLarge `
-ImageName $vmImageName `
-MediaLocation $vmVHDLocation `
-DiskLabel "OS" `
-AvailabilitySetName "WebAvailabilitySet" |
Add-AzureProvisioningConfig `
-WindowsDomain `
-DisableAutomaticUpdates `
-DisableWinRMHttps `
-NoRDPEndpoint `
-Domain $domainName `
-JoinDomain $domainNameFQ `
-DomainPassword $domainAdminPassword `
-DomainUserName $domainAdminUserName `
-AdminUsername $vmAdminUserName `
-Password $vmAdminPassword |
Set-AzureSubnet `
-SubnetNames "WebNet" |
Add-AzureEndpoint `
-DefaultProbe `
-LBSetName "https Load Balancer" `
-LocalPort 443 `
-PublicPort 443 `
-Name "https" `
-Protocol tcp |
New-AzureVM `
Page 76 of 86
-ServiceName $cloudServiceName
# Loop until Satus = ReadyRole...
Write-Host "`tWaiting for Provisioning to Complete..."
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
While ($VMStatus.InstanceStatus -ne "ReadyRole")
{
write-host "`t`tWaiting...Current Status = " $VMStatus.InstanceStatus
Start-Sleep -Seconds 15
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
}
19.1.1. Validation
There are two ways to verify that the virtual machine was created:

Portal – In the Windows Azure Management Portal, click Virtual Machines and then verify that the virtual
machine exists (you might need to refresh the page).

PowerShell – Run the following Windows PowerShell command (include the same variable script block used to
run the command above). It should return the value True.
((Get-AzureVM -name "BIPaper-WFE1" -ServiceName $cloudServiceName) -ne $NULL)
19.2.
Join SharePoint Farm
To join this machine to the SharePoint farm, run the following script from the target server using the on-box variable
block defined earlier in this document (you will be prompted for the farm passphrase that you provided when you
initially created the farm).
# Variable block...
$farmPassphraseSecure = Read-Host -AsSecureString -Prompt "Farm Passphrase"
# Convert Passwords...
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($farmPassphraseSecure)
$farmPassphrase = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Configure SharePoint...
C:
CD "\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\BIN\"
.\psconfig.exe `
-cmd configdb -connect -server $dbServer -database 'SharePoint_Config' -passphrase
$farmPassphrase `
-cmd helpcollections -installall `
-cmd secureresources `
-cmd services -install `
-cmd installfeatures `
-cmd applicationcontent -install `
-cmd quiet
19.2.1. Validation
To verify that this server was added to the farm successfully:
1) Log in to the target server.
2) Open a SharePoint 2013 Management Shell.
Page 77 of 86
3) Run the following command (it should return the value True).
((Get-SPServer | Where {$_.Address -eq "BIPaper-WFE1"}) -ne $NULL)
19.3.
Import Certificate
To import the self-signed SSL certificate that was created in an earlier step, run the following command on the target
server using the on-box variable block defined earlier in this document (you will be prompted for the certificate
password that you used when the certificate was created). If you did not use the default name for the App-tier server,
change the name in this script from “BIPaper-App1” to the server name that you used.
Note: You will need to run this script in an elevated Windows PowerShell window because it needs access to a local
machine resource.
# Variable Block...
$appServerName = "BIPaper-App1"
# Import the Certificate...
$certPassword = Read-Host -AsSecureString -Prompt "Certificate Password"
Import-PfxCertificate –FilePath "\\$appServerName\C$\temp\$cloudServiceName.cloudapp.net.pfx"
cert:\localMachine\my -Password $certPassword
# Bind the Certificate...
$cert = Get-ChildItem cert:\LocalMachine\My | Where {$_.Subject -eq
"CN=$cloudServiceName.cloudapp.net"}
# Create a new binding for the SharePoint site...
New-WebBinding -Name "SharePoint - 80" -Protocol "https" -Port 443 -IPAddress "*"
# Bind the certificate
CD IIS:\SslBindings
$cert | new-item 0.0.0.0!443
19.3.1. Validation
To verify that the certificate was loaded properly:
1) Log in to the server.
2) Start Internet Information Services (IIS) Manager.
3) In the left-hand tree view, expand the server name, expand Sites, right-click SharePoint – 80, and then click Edit
Bindings.
4) In the Site Bindings dialog box, select https and then click Edit.
5) Verify that the SSL certificate is the name of your cloud service’s public URL (<cloudservice>.cloudapp.net).
19.4.
Deploy PowerPivot Solutions
To deploy the PowerPivot solutions to this server, run the following script using the on-box variable block defined earlier
in this document.
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
DeployFarmSolution $false
DeployWebAppSolution "http://$cloudServiceName.cloudapp.net/" 2047 $false
Page 78 of 86
19.4.1. Validation
To verify that this command worked, open Internet Explorer on your local workstation, and then navigate to
https://<cloudservicename>.cloudapp.net. You will be warned that the certificate is invalid (because it is self-signed and
not trusted); continue despite the certificate error. When you are prompted for credentials, use either the domain
administrator or the farm service account (both are site collection administrators at this point). You should be directed
to the home page of your site collection. Navigate to the PowerPivot gallery. If the PowerPivot gallery is displayed, the
solution has been successfully deployed.
Note: When your environment is behind a Windows Azure load balancer you do not know what server is rendering your
page. To test against a specific server, verify that it is the only server active in the load balancer.
Tip: To determine which server is serving a load-balanced page, make a slight edit to the Site Icon file (found at
C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\IMAGES\SiteIcon.png) so that
you can see which site a page is being loaded from. This is not a supported production solution, but it can be helpful for
development, test, and POC scenarios.
19.5.
Configure Second SharePoint Web Front End
To configure a second SharePoint Web Front End, use the same scripts that were used with the first VM, but replace
WFE1 with WFE2.
At this point, you have a SharePoint farm with a highly available Web tier. The only item remaining is to make the
Application tier highly available.
To test the load balancing, open the Windows Azure Management Portal and remove one server from the load balancer
at a time to ensure that your site is still functional.
To Overview of the deployment steps
Page 79 of 86
20.
Step 8: Deploy Additional SharePoint Application/Central Administration Servers
As of right now, we have high availability configured at every layer except for one—the SharePoint application tier. In
this section, we will complete our environment by creating a second SharePoint application tier server that runs the
same services as the first SharePoint application tier.
When this section is complete, we will have the following:

SharePoint App Server
o Server Name – BIPaper-App2
o Storage Account – <your globally unique name>
o Domain/Forest Name – BIPaper.local
o Network Subnet – AppNet
o Availability Set – AppAvailabilitySet
o Joined to SharePoint Farm
o PowerPivot Solutions Deployed
o Reporting Services installed and running
o PowerPivot Service installed and running
o Central Administration running
o Other Non-Standard SharePoint Services Running
 Claims to Windows Token Service
 Excel Calculation Services
 Secure Store Service
If you feel comfortable creating this environment on your own, you can do so – this is the last step in the creation
process.
20.1.
Provision VM
This is the only off-box task within the scope of creating the second SharePoint application tier server. All other scripts
will be run in a remote desktop session on the machine. The script consists of the following elements:


Variable Block – This section gathers information (in addition to the standard variable block you provide as
outlined earlier in the document).
VM Creation – This section (starting with the comment “Creating the virtual machine…”) consists of the
following Windows Azure commands:
o New-AzureVMConfig – This command begins the definition of the virtual machine. It sets the name, size,
image, .vhd location and label, and availability set.
o Add-AzureProvisioningConfig – This command determines how Windows Azure should provision the VM
defined in the last command. It tells Windows Azure that this will be a Windows machine, that
automatic updates should be disabled (you can turn this back on if you want), that there should not be
endpoints for RDP or Remote Windows PowerShell, and what the administrator user and password
should be. Additionally, this command provides the information necessary to automatically join the
machine to our domain.
o Set-AzureSubnet – This command defines what subnet the virtual machine should be deployed into.
o New-AzureVM – This command does the work of creating the virtual machine that was defined in the
earlier commands. In addition to the information gathered from the earlier commands, it defines the
cloud service that should be used. The script loops until creation of the VM is complete and writes a
status to the screen every 15 seconds.
To create the second SharePoint application server, run the following Windows Azure PowerShell command (use the
variable/subscription block with the storage account defined).
Page 80 of 86
# Get the name for the VM...
$vmName = "BIPaper-App2"
$vmImageName = "BIPaper-SharePoint"
# Get the admin user name for the VM...
$vmAdminUserName = Read-Host -Prompt "Server Administrator User Name"
# Ask for the password that should be used for the server and convert it to a format usable by the
commands...
$vmAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Server Administrator Password"
$stringMarshal =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($vmAdminPasswordSecure)
$vmAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal)
# Get the domain admin user name...
$domainAdminUserName = Read-Host -Prompt "Domain Administrator User Name"
# Ask for the domain admin password and convert it to a format usable by the commands...
$domainAdminPasswordSecure = Read-Host -AsSecureString -Prompt "Domain Administrator Password"
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($domainAdminPasswordSecure)
$domainAdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Set the location of the .vhd files...
$storageAccountContainer = "https://" + $storageAccountName + ".blob.core.windows.net/vhds/"
$vmVHDLocation = $storageAccountContainer + $vmName + ".vhd"
# Create the virtual machine...
Write-Host "Creating the VM..."
New-AzureVMConfig `
-Name $vmName `
-InstanceSize ExtraLarge `
-ImageName $vmImageName `
-MediaLocation $vmVHDLocation `
-DiskLabel "OS" `
-AvailabilitySetName "AppAvailabilitySet" |
Add-AzureProvisioningConfig `
-WindowsDomain `
-DisableAutomaticUpdates `
-DisableWinRMHttps `
-NoRDPEndpoint `
-Domain $domainName `
-JoinDomain $domainNameFQ `
-DomainPassword $domainAdminPassword `
-DomainUserName $domainAdminUserName `
-AdminUsername $vmAdminUserName `
-Password $vmAdminPassword |
Set-AzureSubnet `
-SubnetNames "AppNet" |
New-AzureVM `
-ServiceName $cloudServiceName
# Loop until Satus = ReadyRole...
Write-Host "`tWaiting for Provisioning to Complete..."
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
While ($VMStatus.InstanceStatus -ne "ReadyRole")
{
write-host "`t`tWaiting...Current Status = " $VMStatus.InstanceStatus
Start-Sleep -Seconds 15
$VMStatus = Get-AzureVM -name $vmName -ServiceName $cloudServiceName
}
20.1.1. Validation
There are two ways to verify that the virtual machine was created:

Portal – In the Windows Azure Management Portal, click Virtual Machines and then verify that the virtual
machine exists (you might need to refresh the page).
Page 81 of 86

PowerShell – Run the following Windows PowerShell command (include the same variable script block used to
run the command listed earlier). It should return the value True.
((Get-AzureVM -name "BIPaper-App2" -ServiceName $cloudServiceName) -ne $NULL)
20.2.
Join SharePoint Farm
To join this machine to the SharePoint farm, run the following script on the target server using the on-box variable block
defined earlier in this document (you will be prompted for the farm passphrase that you provided when you initially
created the farm).
# Variable block...
$farmPassphraseSecure = Read-Host -AsSecureString -Prompt "Farm Passphrase"
# Convert Passwords...
$stringMarshal2 =
[System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($farmPassphraseSecure)
$farmPassphrase = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($stringMarshal2)
# Configure SharePoint...
C:
CD "\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\BIN\"
.\psconfig.exe `
-cmd configdb -connect -server $dbServer -database 'SharePoint_Config' -passphrase
$farmPassphrase `
-cmd helpcollections -installall `
-cmd secureresources `
-cmd services -install `
-cmd installfeatures `
-cmd adminvs -provision -port 8080 -windowsauthprovider onlyusentlm `
-cmd applicationcontent -install `
-cmd quiet
20.2.1. Validation
To verify that this server was added to the farm successfully:
1) Log in to the target server.
2) Open a SharePoint 2013 Management Shell.
3) Run the following command (it should return the value True).
((Get-SPServer | Where {$_.Address -eq "BIPaper-App2"}) -ne $NULL)
20.3.
Configure Local Service Instances
To configure and start the PowerPivot service on this machine, run the following script on the target server (a variable
block is not required).
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
New-PowerPivotSystemServiceInstance -Provision:$true
20.3.1. Validation
To verify that the service was started successfully:
Page 82 of 86
1) Log in to the target server.
2) Open a SharePoint 2013 Management Shell.
3) Run the following command (it should return the value True).
((Get-SPServiceInstance -Server "BIPaper-App2" | Where {$_.TypeName -eq "SQL Server PowerPivot
System Service" -and $_.Status -eq "Online"}) -ne $NULL)
20.4.
Start the SharePoint Services
To start the non-standard SharePoint services, run the following script on the target server (a variable block is not
required).
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
Start-SPServiceInstance -Identity (Get-SPServiceInstance -Server $env:COMPUTERNAME | where
{$_.TypeName -eq "Claims to Windows Token Service"}).Id
Start-SPServiceInstance -Identity (Get-SPServiceInstance -Server $env:COMPUTERNAME | where
{$_.TypeName -eq "Excel Calculation Services"}).Id
Start-SPServiceInstance -Identity (Get-SPServiceInstance -Server $env:COMPUTERNAME | where
{$_.TypeName -eq "Secure Store Service"}).Id
20.4.1. Validation
To verify that the services were started successfully:
1) Log in to the target server.
2) Open a SharePoint 2013 Management Shell.
3) Run the following commands (each should return the value True).
((Get-SPServiceInstance -Server "BIPaper-App2" | Where {$_.TypeName -eq "Claims to Windows Token
Service" -and $_.Status -eq "Online"}) -ne $NULL)
((Get-SPServiceInstance -Server "BIPaper-App2" | Where {$_.TypeName -eq "Excel Calculation
Services" -and $_.Status -eq "Online"}) -ne $NULL)
((Get-SPServiceInstance -Server "BIPaper-App2" | Where {$_.TypeName -eq "Secure Store Service" -and
$_.Status -eq "Online"}) -ne $NULL)
20.5.
Deploy PowerPivot Solutions
To deploy the PowerPivot solutions to this server, run the following script using the on-box variable block defined earlier
in this document.
Add-PSSnapin Microsoft.SharePoint.Powershell
Import-Module "C:\Program Files\Microsoft SQL
Server\110\Tools\PowerPivotTools\SPAddinConfiguration\Resources\ConfigurePowerPivot.ps1"
DeployFarmSolution $false
DeployWebAppSolution "http://$cloudServiceName.cloudapp.net/" 2047 $false
20.5.1. Validation
To verify that the solutions were deployed successfully:
1) Log in to the target server.
Page 83 of 86
2) Open Internet Explorer. You will need to disable Internet Explorer Enhanced Security Configuration (ESC) for this
to work.
3) Navigate to http://bipaper-app2 (or the name of the server you chose if you changed it). You might get an
unexpected error the first time you browse to the site—if you refresh the page it should work properly.
4) Browse to the PowerPivot gallery.
5) If the solutions were not deployed properly, you will receive a “File not found” error when you browse to the
PowerPivot gallery.
20.6.
Install Reporting Services Bits
This step installs the SQL Server Reporting Services binaries onto the SharePoint application tier. This only needs to be
run on servers that will act as report servers—Web Front End servers do not need to have these binaries installed.
Note: This step requires installation media for SQL Server 2012 (to install Reporting Services). Place the information in
the following directories on the VM:


D:\SQL Server 2012\ – This should be the contents of the SQL Server installation media (use the media with SP1
slipstreamed). Do not just put the .iso file in this directory—it needs to be the contents of the media extracted.
D:\SQL Server 2012 CU\ – This should be the .exe file that you would run to apply the CU. The CUs are delivered
as executable .zip files, the contents of which are what we are looking for in this directory.
To install Reporting Services, run the following script on the target server (no variable block is required, but you are
prompted for your SQL Server license key).
# Get the SQL Server license key...
$sqlpid = Read-Host -Prompt "SQL Server License Key"
# Install SQL Server...
D:
CD "\SQL Server 2012"
.\setup.exe `
/Action=Install `
/PID="$sqlpid" `
/IACCEPTSQLSERVERLICENSETERMS `
/ENU `
/UpdateEnabled=1 `
/UpdateSource="D:\SQL Server 2012 CU" `
/ErrorReporting=0 `
/Features=RS_SHP `
/IndicateProgress `
/QS
You now need to restart the server.
20.6.1. Validation
To verify that Reporting Services was installed properly:
1) Log in to the server.
2) Open Windows Explorer.
3) Navigate to “C:\Program Files\Microsoft SQL Server\110\Setup Bootstrap\Log”, and then open the
“Summary.txt” file.
4) Verify that the Final result is Passed but reboot required, see logs for details.
5) Verify that the Exit code (Decimal) is 3010.
20.7.
Enable Reporting Services
To enable the Reporting Services bits within SharePoint, run the following script on the target server (no variable block is
required).
Page 84 of 86
Add-PSSnapin Microsoft.SharePoint.Powershell
$RS = Get-SPServiceInstance -Server $env:COMPUTERNAME | Where {$_.TypeName -eq "SQL Server
Reporting Services Service"}
if ($RS -eq $NULL)
{
Install-SPRSService
Install-SPRSServiceProxy
}
$RS = Get-SPServiceInstance -Server $env:COMPUTERNAME | Where {$_.TypeName -eq "SQL Server
Reporting Services Service"}
Start-SPServiceInstance -Identity $RS.Id.ToString()
20.7.1. Validation
To verify that Reporting Services was successfully enabled:
1) Log in to the server.
2) Open a SharePoint 2013 Management Shell.
3) Run the following script (it should return the value True).
(((Get-SPServiceInstance -Server $env:COMPUTERNAME | where {$_.TypeName -eq "SQL Server
Reporting Services Service"}).Status -eq "Online") -ne $NULL)
To Overview of the deployment steps
Page 85 of 86
21.
Conclusion
In this paper, we built a full lab environment consisting of:




A domain
A database back-end
A SharePoint farm with separate Web Front Ends, and PowerPivot installed and configured.
High availability built in at each tier
The entire environment was deployed using Windows Azure Virtual Machines. You could easily modify these
instructions to make a smaller or larger farm. That was our goal, to give you the information that you needed to
move forward and build your own customized environment. The environment was built with only the SharePoint
components that are required to get the BI environment working. You could add additional options (such as search)
if your environment requires them.
While all of the steps included a cloud component, the SharePoint installation and configuration used applies to onpremises installations as well, both on physical hardware and virtualized.
If you want to work in a non-cloud environment, just start each section after the VM is provisioned (and change your
machine/domain naming accordingly).
You could even explore more of the Windows Azure Virtual Network options for on-prem connectivity and configure
your environment to trust an on-prem domain or even join your cloud-based machines to an existing on-prem
domain.
21.1.
For more information:
SQL Server Business Intelligence in Windows Azure Virtual Machines:
http://msdn.microsoft.com/en-us/library/windowsazure/jj992719.aspx
Single server sample scripts, see http://azuresql.codeplex.com/releases/view/104386.
White paper http://blogs.msdn.com/b/sqlcat/archive/2013/06/17/performance-guidance-for-sqlserver-in-windows-azure-virtual-machines.aspx.
SQL Server TechCenter: http://technet.microsoft.com/en-us/sqlserver/:
SQL Server DevCenter: http://msdn.microsoft.com/en-us/sqlserver/
Primary SQL Server Portal: http://www.microsoft.com/sqlserver/:
21.2.
Feedback
Did this paper help you? Please give us your feedback. Tell us on a scale of 1 (poor) to 5
(excellent), how would you rate this paper and why have you given it this rating? For example:


Are you rating it high due to having good examples, excellent screen shots, clear writing, or
another reason?
Are you rating it low due to poor examples, fuzzy screen shots, or unclear writing?
This feedback will help us improve the quality of white papers we release.
Send feedback.
Page 86 of 86