You are on page 1of 90

Deploy SQL Server Business

Intelligence in Windows Azure Virtual


Machines
Chuck Heinzelman

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.

Category: Step-by-Step
Applies to: SQL Server 2012 SP1, Windows Azure
E-book publication date: August 2013

Page 1 of 89

Page 2 of 89

Copyright 2012 by Microsoft Corporation


All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any means
without the written permission of the publisher.

Microsoft and the trademarks listed at http://www.microsoft.com/about/legal/en/us/IntellectualProperty/Trademarks/ENUS.aspx are trademarks of the Microsoft group of companies. All other marks are property of their respective owners.
The example companies, organizations, products, domain names, email addresses, logos, people, places, and events
depicted herein are fictitious. No association with any real company, organization, product, domain name, email address,
logo, person, place, or event is intended or should be inferred.
This book expresses the authors views and opinions. The information contained in this book is provided without any
express, statutory, or implied warranties. Neither the authors, Microsoft Corporation, nor its resellers, or distributors will
be held liable for any damages caused or alleged to be caused either directly or indirectly by this book.

Page 3 of 89

1. Contents
1.

Contents .......................................................................................................................................................................... 4

2.

Introduction .................................................................................................................................................................... 9

3.

What Is Infrastructure as a Service (IaaS)? ..................................................................................................................... 9

4.

Why Infrastructure as a Service (IaaS)? .......................................................................................................................... 9

5.

Recommended Scenarios for BI on IaaS ....................................................................................................................... 10

6.

Document Conventions ................................................................................................................................................ 10

7.

Getting Started with IaaS .............................................................................................................................................. 11


7.1.

Affinity Groups ...................................................................................................................................................... 11

7.2.

Virtual Networks ................................................................................................................................................... 11

7.2.1.

Subnets.......................................................................................................................................................... 12

7.2.2.

DNS ................................................................................................................................................................ 12

7.2.3.

On-Premises Connectivity ............................................................................................................................. 12

7.3.

Storage .................................................................................................................................................................. 13

7.3.1.

Containers ..................................................................................................................................................... 13

7.3.2.

Access Keys ................................................................................................................................................... 14

7.4.

Cloud Service......................................................................................................................................................... 14

7.4.1.

Deployments ................................................................................................................................................. 14

7.4.2.

Virtual IP Address .......................................................................................................................................... 14

7.5.

Endpoints .............................................................................................................................................................. 14

7.6.

Virtual Machines ................................................................................................................................................... 15

7.7.

Availability Sets ..................................................................................................................................................... 15

7.8.

Disks ...................................................................................................................................................................... 15

7.9.

Images ................................................................................................................................................................... 15

8.

Prerequisites and Assumptions..................................................................................................................................... 17

9.

Windows Azure PowerShell Commands ....................................................................................................................... 18

10.

Non-Windows Azure PowerShell Commands ........................................................................................................... 20

11.

The Overall Environment .......................................................................................................................................... 21

12.

Overview of the Deployment Steps .......................................................................................................................... 23

13.

Step 1: Configure the Windows Azure Environment ................................................................................................ 24

13.1.
13.1.1.
13.2.

Create the Affinity Group .................................................................................................................................. 24


Validation ...................................................................................................................................................... 24
Network ............................................................................................................................................................ 25
Page 4 of 89

13.2.1.

Create the Virtual Network ........................................................................................................................... 25

13.2.2.

Validation ...................................................................................................................................................... 27

13.2.3.

Point-to-Site VPN .......................................................................................................................................... 28

13.3.
13.3.1.

Create the Cloud Service ............................................................................................................................... 28

13.3.2.

Validation ...................................................................................................................................................... 28

13.4.

14.

Storage Account ................................................................................................................................................ 28

13.4.1.

Create the Storage Account .......................................................................................................................... 28

13.4.2.

Validation ...................................................................................................................................................... 29

Step2: Deploy Active Directory Domain Services ..................................................................................................... 30

14.1.

First Domain Controller ..................................................................................................................................... 30

14.1.1.

Provision VM ................................................................................................................................................. 31

14.1.2.

Validation ...................................................................................................................................................... 33

14.1.3.

Format Disks.................................................................................................................................................. 34

14.1.4.

Create Domain .............................................................................................................................................. 34

14.1.5.

Create Sites and Subnets .............................................................................................................................. 35

14.1.6.

Remove Forwarder ....................................................................................................................................... 37

14.2.

Second Domain Controller ................................................................................................................................ 37

14.2.1.

Provision VM ................................................................................................................................................. 37

14.2.2.

Format Disks.................................................................................................................................................. 41

14.2.3.

Create Domain Controller ............................................................................................................................. 41

14.2.4.

Create Share .................................................................................................................................................. 42

14.3.
14.3.1.
15.

Cloud Service ..................................................................................................................................................... 28

Service User Accounts ....................................................................................................................................... 42


Create Service User Accounts ....................................................................................................................... 43

Step 3: Configure SQL Server Database Servers (SharePoint Back End) ................................................................... 46

15.1.
15.1.1.

First SQL Server Instance................................................................................................................................... 47


Provision VM ................................................................................................................................................. 47

15.2.

Format Disks...................................................................................................................................................... 49

15.3.

Enable Clustering .............................................................................................................................................. 49

15.4.

Install SQL Server .............................................................................................................................................. 49

15.5.

Second SQL Server Instance .............................................................................................................................. 51

16.

Step 4: Configure SQL Server PowerPivot Servers .................................................................................................... 52

16.1.

First PowerPivot Server ..................................................................................................................................... 53


Page 5 of 89

16.1.1.

Provision VM ................................................................................................................................................. 53

16.1.2.

Install SQL Server .......................................................................................................................................... 55

16.2.
17.

Step 5: Deploy the first SharePoint Application/Central Administration Server ...................................................... 57

17.1.

SharePoint Image .............................................................................................................................................. 57

17.1.1.

Provision VM ................................................................................................................................................. 57

17.1.2.

Install SharePoint Prerequisites .................................................................................................................... 59

17.1.3.

Install SharePoint .......................................................................................................................................... 60

17.1.4.

Install Add-Ins................................................................................................................................................ 60

17.1.5.

Install Updates .............................................................................................................................................. 61

17.1.6.

Sysprep .......................................................................................................................................................... 61

17.1.7.

Capture Image ............................................................................................................................................... 61

17.2.

First SharePoint Server...................................................................................................................................... 62

17.2.1.

Provision VM ................................................................................................................................................. 62

17.2.2.

Create New Farm .......................................................................................................................................... 64

17.2.3.

Add PowerPivot Solutions ............................................................................................................................. 64

17.2.4.

Install PowerPivot Features .......................................................................................................................... 65

17.2.5.

Configure Service Instance............................................................................................................................ 65

17.2.6.

Create PowerPivot Service Application......................................................................................................... 65

17.2.7.

Create Default Web Application ................................................................................................................... 65

17.2.8.

Deploy Web Application Solution ................................................................................................................. 66

17.2.9.

Create Site Collection .................................................................................................................................... 66

17.2.10.

Activate PowerPivot Feature .................................................................................................................... 66

17.2.11.

Start the Claims to Windows Token Service ............................................................................................. 66

17.2.12.

Configure Secure Store Service ................................................................................................................. 67

17.2.13.

Configure Alternate Access Mappings ...................................................................................................... 68

17.2.14.

Install Reporting Services .......................................................................................................................... 69

17.2.15.

Install Reporting Services Bits ................................................................................................................... 69

17.2.16.

Enable Reporting Services ......................................................................................................................... 70

17.2.17.

Create Reporting Services Shared Service Application ............................................................................. 71

17.2.18.

Grant Reporting Services permissions ...................................................................................................... 71

17.3.
18.

Second PowerPivot Server ................................................................................................................................ 56

Section Validation ............................................................................................................................................. 72

Step 6: Configure AlwaysOn Availability Groups ...................................................................................................... 73


Page 6 of 89

18.1.
18.1.1.
18.2.
18.2.1.
18.3.
18.3.1.
18.4.
18.4.1.
19.

Validation ...................................................................................................................................................... 74
Enable AlwaysOn Availability Groups ............................................................................................................... 74
Validation ...................................................................................................................................................... 75
Create Availability Group .................................................................................................................................. 75
Validation ...................................................................................................................................................... 76
Enable High Availability in SharePoint .............................................................................................................. 77
Validation ...................................................................................................................................................... 77

Step 7: Deploy SharePoint Web Front End Servers .................................................................................................. 78

19.1.
19.1.1.
19.2.
19.2.1.
19.3.
19.3.1.
19.4.
19.4.1.
19.5.
20.

Create Cluster ................................................................................................................................................... 73

Provision VM ..................................................................................................................................................... 78
Validation ...................................................................................................................................................... 80
Join SharePoint Farm ........................................................................................................................................ 80
Validation ...................................................................................................................................................... 80
Import Certificate .............................................................................................................................................. 81
Validation ...................................................................................................................................................... 81
Deploy PowerPivot Solutions ............................................................................................................................ 81
Validation ...................................................................................................................................................... 82
Configure Second SharePoint Web Front End .................................................................................................. 82

Step 8: Deploy Additional SharePoint Application/Central Administration Servers ................................................ 83

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.

Provision VM ..................................................................................................................................................... 83
Validation ...................................................................................................................................................... 84
Join SharePoint Farm ........................................................................................................................................ 85
Validation ...................................................................................................................................................... 85
Configure Local Service Instances ..................................................................................................................... 85
Validation ...................................................................................................................................................... 85
Start the SharePoint Services ............................................................................................................................ 86
Validation ...................................................................................................................................................... 86
Deploy PowerPivot Solutions ............................................................................................................................ 86
Validation ...................................................................................................................................................... 86
Install Reporting Services Bits ........................................................................................................................... 87
Validation ...................................................................................................................................................... 87
Enable Reporting Services ................................................................................................................................. 87
Validation ...................................................................................................................................................... 88
Page 7 of 89

21.

Conclusion ................................................................................................................................................................. 89

21.1.

For more information: ...................................................................................................................................... 89

21.2.

Feedback ........................................................................................................................................................... 89

Page 8 of 89

2. Introduction
Weve 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 Azure-based 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.

Page 9 of 89

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 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 flexibilitydifferent 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 10 of 89

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 papers 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/enus/documentation/services/virtual-machines/?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 itVMs 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 wantthe 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 timeconsuming, 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.

Page 11 of 89

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 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-to-site 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
Page 12 of 89

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.
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:

Page 13 of 89

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.

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 serviceunless 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.
Page 14 of 89

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 onpremises. 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 cautionmake 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 15 of 89

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 16 of 89

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/enus/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/cloudspelunking-managing-azure-form-your-desktop-via-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

Page 17 of 89

to do this, see Configure a Point-to-Site 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/enus/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 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

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
Page 18 of 89

$affinityGroupLabel
$virtualNetworkName
$cloudServiceName
$cloudServiceDescription
$cloudServiceLabel
$storageAccountName
$storageAccountLabel
$domainName
$domainNameFQ

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.
# 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: GetAzureLocation | 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.
Page 19 of 89

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

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.
Page 20 of 89

# 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.

A second SharePoint application-tier server (BiPaper-App2) for HA

Page 21 of 89

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 22 of 89

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

Deploy Active Directory Domain


Services (AD DS)

Configure SQL Server Database


Servers
Configure PowerPivot Servers

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 23 of 89

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 24 of 89

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 25 of 89

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 26 of 89

# 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 27 of 89

((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 28 of 89

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 29 of 89

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
rolein 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 30 of 89

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
papers 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
papers 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 31 of 89

# 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 32 of 89

$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 33 of 89

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 34 of 89

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 35 of 89

-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 36 of 89

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 37 of 89

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
papers 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
papers 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 38 of 89

-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 39 of 89

}
# 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 40 of 89

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 41 of 89

-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 42 of 89

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 organizations 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 43 of 89

# 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 44 of 89

# 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 45 of 89

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 46 of 89

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 directoryit 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 47 of 89

# 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 48 of 89

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 49 of 89

Important: Dont 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 50 of 89

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 51 of 89

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 systems 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 52 of 89

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 directoryit 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 53 of 89

# 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 54 of 89

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: Dont 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 55 of 89

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 56 of 89

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 partsimage 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 57 of 89

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 58 of 89

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: Dont 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 59 of 89

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: Dont 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: Dont 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 60 of 89

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 61 of 89

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 directoryit 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 62 of 89

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 63 of 89

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 accountif 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 farmit 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 64 of 89

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 65 of 89

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 66 of 89

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 67 of 89

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 68 of 89

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 havent 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 services 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 serversWeb 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 directoryit 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 69 of 89

# 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 70 of 89

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 71 of 89

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 havent 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 72 of 89

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 havent 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 73 of 89

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 dont 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 74 of 89

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 75 of 89

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 76 of 89

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 77 of 89

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 78 of 89

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 79 of 89

-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 80 of 89

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 services 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 81 of 89

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 82 of 89

20.

Step 8: Deploy Additional SharePoint Application/Central Administration Servers

As of right now, we have high availability configured at every layer except for onethe 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 83 of 89

# 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 84 of 89

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 85 of 89

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 86 of 89

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 siteif 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 serversWeb 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 directoryit 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 87 of 89

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 88 of 89

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 89 of 89

You might also like