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