64
The New World of Tenant Provisioning Published: 2014 For the latest information, please see http://aka.ms/BuildingClouds

The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

  • Upload
    lytruc

  • View
    219

  • Download
    0

Embed Size (px)

Citation preview

Page 1: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

The New World of Tenant ProvisioningPublished: 2014

For the latest information, please see http://aka.ms/BuildingClouds

Page 2: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Introduction.....................................................................................................1So, what is this white paper all about?..........................................................1

Background......................................................................................................2Looking Back.................................................................................................2What can we salvage?...................................................................................2What’s new?..................................................................................................2

Download.........................................................................................................3

Automated Deployment of Tenant Network and Identity Workload.................4Automated Tenant Virtual Network Deployment..........................................4Create a VM Network “OnBehalfOf” a User Role...........................................5Automated Active Directory VMRole Deployment.........................................7The Options...................................................................................................7The Process...................................................................................................8Even More Magic – Bearer Tokens...............................................................10The overall structure of the SMA Runbooks................................................11Deploy a Gallery Item VMRole.....................................................................13BONUS - Example VMM PowerShell for Gallery Item VMRole Deployment!.20Use Cases....................................................................................................21

Automated Deployment of the Identity Workload as a Tenant Admin...........22The Options.................................................................................................23The Process.................................................................................................24The Pre-Requisites......................................................................................25The Pre-Requisite Setup..............................................................................26Active Directory Gallery Item VMRole Deployment as a Tenant Admin......27Use Cases....................................................................................................31

Automated Deployment of Tenant Workloads (Lync, SharePoint, and Exchange)......................................................................................................32

The Scope...................................................................................................33Out of Scope................................................................................................34Deployment as a Service Administrator in SMA (with the WAP Tenant API Only)...........................................................................................................34

The New World of Tenant Provisioning

Page 3: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Existing: SMA Runbook that is the same for each Gallery Item VMRole Deployment.................................................................................................34New: Updated SMA Runbooks…..................................................................35…for the Lync Gallery Item VMRole Deployment........................................36…for the SharePoint Gallery Item VMRole Deployment...............................36…for the Exchange Gallery Item VMRole Deployment................................36Future Discovery: How to enumerate ResDef/ResDefExt and ResDefConfig Requirements for any Gallery Item VMRole................................................38Deployment as a Tenant Administrator from a PowerShell Script (with the Public WAP Tenant API)...............................................................................40New: Deployment Script for Active Directory, Lync, Exchange, or SharePoint....................................................................................................................40Future Discovery: Modified Example PowerShell script to enumerate ResDef/ResDefExt and ResDefConfig Requirements for any Gallery Item VMRole........................................................................................................44Use Cases....................................................................................................45

Appendix........................................................................................................46Links Referenced within the Document.......................................................46Links from the Related Blog Series.............................................................47Links to Other Related and Valuable Content.............................................47

The New World of Tenant Provisioning

Page 4: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

IntroductionTo be clear, this document is all about [on-prem] Automated Tenant Provisioning with [Windows] Azure Pack (WAP). And WAP is just one of the primary technologies leveraged within this example. In fact, Service Management Automation (SMA), PowerShell, PowerShell Workflow, Virtual Machine Manager (VMM), and VMRole Gallery Items, are the backbone of the [example] solution.

Note The guidance here was previously published blog content found on the Building Clouds Blog.

So, what is this white paper all about?

Applying existing knowledge of tenant provisioning techniques in this “new world”

Transforming existing knowledge (Service Templates) of tenant workload deployments into “Azure Pack friendly” workload deployments (VMRoles)

Providing new automation (PowerShell scripts) for the latest tenant provisioning technology (Azure Pack)

1 The New World of Tenant Provisioning

Page 5: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

BackgroundLooking BackIf you have been following my work on the Building Clouds Blog, you may remember the following two blog posts:

Automation–PowerShell Workflow Script Spotlight–Deploying Virtual Machine Manager Service Templates “OnBehalfOf” Tenant Administrator User Roles

Automation–PowerShell Workflow Script Spotlight–Creation and Parameterization of Virtual Machine Manager Run As Accounts for “OnBehalfOf” Service Template Deployment

Well, those were directly related to the initial learning around Tenant Provisioning my team gathered during an internal Proof of Concept. Back then, it was all about the “VMM Service Template”, and while some of that existing knowledge will work in this new world of Azure Pack, the focus now is on VMRoles as the delivery mechanism for application workloads.

What can we salvage?At the very least, all the existing knowledge around automated deployment of the Tenant Virtual Network (Isolated Software Defined Network (SDN)). As well as, some previously undisclosed techniques for automatically initiating the deployments - all of which still holds true, regardless of delivery mechanism.

What’s new?The new automation involved in the deployment of VMRoles, as both a Service Admin (via VMM “OnBehalfOf” PS Commands) and a Tenant Admin (via the Service Management WS API).

2 The New World of Tenant Provisioning

Page 6: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

DownloadThe download for all the artifacts within this example solution can be found on TechNet Gallery. The downloadable content introduces a collection of example PowerShell Scripts and SMA Runbooks that you can use to Automate Tenant Provisioning of Gallery Item VMRoles within WAP.URL: http://gallery.technet.microsoft.com/Windows-Azure-Pack-Tenant-3e8afd64

The download (Windows Azure Pack Tenant Provisioning Automation Toolkit.zip) includes (14) files:For the Service Administrator

SMA Runbook Exports (5 files)o Create-VMNetwork.xml o Deploy-TenantVMRole.xml o Deploy-VMRole.xml o Subscription-Create-Dispatcher.xml o VMRole-Create-Dispatcher.xml

PowerShell Scripts (2 files)o Deploy-VMRole_OptionalVMMCommands.ps1 o Get-GIResourceParams_asServiceAdmin.ps1

PowerShell Workflows (5 files)o Create-VMNetwork.ps1 o Deploy-TenantVMRole.ps1 o Deploy-VMRole.ps1 o Subscription-Create-Dispatcher.ps1 o VMRole-Create-Dispatcher.ps1

For the Tenant Administrator

PowerShell Scripts (2 files)o Deploy-TenantVMRoles_asTenantAdmin.ps1 o Get-GIResourceParams_asTenantAdmin.ps1

Note     XML (SMA Runbooks) and PS1 (PowerShell Scripts) files are both provided in the download. Use SMART for Runbook Import and Export to leverage the provided XML files in the above download for an enhanced experience in importing the example solution into your SMA environment.

Optional     Some of the scripts within this download contain commented out “optional” portions for Monitoring and Notifications. The associated Runbooks and Variables for these options are not included in this download. For more information about Monitoring and Notifications within SMA, please see the following blog post: Automation–Monitoring and Notifying in Windows Azure Pack with SMA

3 The New World of Tenant Provisioning

Page 7: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Automated Deployment of Tenant Network and Identity WorkloadWhat does that mean, exactly?

Well for the context of this document, it means I am going to provide the PowerShell/SMA Runbook scripts necessary to create a Tenant Virtual Network (Isolated Software Defined Network (SDN)) & Active Directory VMRole. So, for organization’s sake, this section of the document will be split into two main sections – one for automated Tenant Virtual Network deployment, and one for automated VMRole deployment.

Automated Tenant Virtual Network DeploymentFor the most part, the PowerShell/SMA Runbook example for this already exists. Granted, you would have to be a Building Clouds Blog super-fan to know exactly where it is, but it does exist on the blog. That said, for this document, we want to promote it much more, and underline the significance of it in this example solution.So where did this example live before being reestablished here?

In this blog post: Automation–PowerShell Workflow Script Spotlight–Deploying Virtual Machine Manager Service Templates “OnBehalfOf” Tenant Administrator User Roles

An admittedly, under-promoted yet valuable blog post on the automation of various VMM resources via PowerShell workflow, from the Service Administrator “OnBehalfOf” the Tenant Administrator.In fact, I believe now is a great time to take a moment and describe the “Scope of Management” for these two personas in an image:

4 The New World of Tenant Provisioning

Page 8: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

The reason I believe this is important, is that I will be referring to each persona throughout the document. Now, this is not a comprehensive list of all the potential areas each persona has management over, but it covers what we need here.Note     There may be other uses or ways to access the WAP Tenant API (non-Public) than just as a Service Administrator. From what I have seen, it requires bearer token authorization. And since the best way to get this token is via the WAP Admin PowerShell Cmdlet (Get-MgmtSvcToken), I made some assumptions.

Create a VM Network “OnBehalfOf” a User RoleThe following PowerShell workflow script (Create-VMNetwork) will create a VMM VM Network with the following settings (leveraging VMM PowerShell Commands):

VM Network Name: <VM Network Name generated by Owner User Role Name defined with parameter>

Subnet Name: <defined in script: “TenantSubnet”> Subnet Value: <defined in script: “192.168.0.0/24”> IP Address Pool Name: <defined in script: “TenantIPPool”> IP Address Range Start: <defined in script: “192.168.0.100”> IP Address Range End: <defined in script: “192.168.0.199” –

providing for 100 available addresses> DNS IP: <defined in script: “192.168.0.100” – first IP in Pool> OnBehalfOfUser: <User Name parsed from Owner User Role Name

defined with parameter> OnBehalfOfUserRole: <User Role parsed from Owner User Role

Name defined with parameter>

Note     You may keep these example settings, or modify to fit your deployment specifications.

Example PowerShell workflow script for Create-VMNetwork001

workflow Create-VMNetwork{

5 The New World of Tenant Provisioning

Page 9: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041

    param    (    [string]$OwnerUserRole,    [string]$VmmServerName,    [string]$CloudName,    [string]$LogicalNetworkName    )     inlinescript    {        $subnetValue = "192.168.0.0/24"        $subnetName = "TenantSubnet"        $dnsIP = "192.168.0.100"        $ipAdressPoolName = "TenantIPPool"        $ipAddressRangeStart = "192.168.0.100"        $ipAddressRangeEnd = "192.168.0.199"        $UserRole = $Using:OwnerUserRole        $User = $UserRole.Split("_")[0]        $vmNetworkName = "Tenant Network ($User)"                Get-SCVMMServer -ComputerName $Using:VmmServerName -ForOnBehalfOf | Out-Null        $OwnerUserRoleObj = Get-SCUserRole | where {$_.Name -match $Using:OwnerUserRole}

        $VMNetwork = Get-SCVMNetwork -OnBehalfOfUser $User -OnBehalfOfUserRole $OwnerUserRoleObj        if(!$VMNetwork) {            $CloudObj = Get-SCCloud -Name $Using:CloudName            $logicalNetwork = Get-SCLogicalNetwork -Cloud $CloudObj -Name $Using:LogicalNetworkName            $vmNetwork = New-SCVMNetwork -Name $vmNetworkName -LogicalNetwork $logicalNetwork `                -OnBehalfOfUser $User -OnBehalfOfUserRole $OwnerUserRoleObj                    $subnet = New-SCSubnetVLan -Subnet $subnetValue             $vmSubnet = New-SCVMSubnet -Name $subnetName -VMNetwork $vmNetwork -SubnetVLan $subnet `                -OnBehalfOfUser $User -OnBehalfOfUserRole $OwnerUserRoleObj

            $allDnsServer = @($dnsIP)

            $staticIPAddressPool = New-SCStaticIPAddressPool -Name $ipAdressPoolName `                -VMSubnet $vmSubnet -Subnet $subnetValue -IPAddressRangeStart $ipAddressRangeStart `                -IPAddressRangeEnd $ipAddressRangeEnd -DNSServer $allDnsServer `                -RunAsynchronously -OnBehalfOfUser $User -OnBehalfOfUserRole $OwnerUserRoleObj        }    }}

6 The New World of Tenant Provisioning

Page 10: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

042043044045

Note     In general, the Create-VMNetwork workflow gets called once per Tenant Admin (Owner User Role, which is the equivalent of User + Plan Subscription). In fact, this workflow is most often called as part of the SMA Runbook linked to the Subscription.Create event within WAP/SPF, meaning that as soon as a Tenant Admin User Subscribes to the related Plan, the Tenant Virtual Network is created automatically for that Subscription. For more information (and a specific example) about how WAP leverages SPF events to initiate SMA Runbooks, see the following TechNet Article: Using automation with Virtual Machine Clouds and blog post: Automation–Monitoring and Notifying in Windows Azure Pack with SMA

Configuring more than just the basics…

For instance, what if you wanted to configure NAT with a specific Gateway Device and External IP Address Pool?

Well, add the following PowerShell to the above example script:

001002003004005006007008009010011

#NAT, Gateway and External IP Address Pool Variables$vmGWServiceName = "Gateway Service Name"$vmNetworkGwName = "{0}_Gateway" -f $vmNetworkName$vmExtStaticIPAddyPoolName = "External IP Address Pool Name"$vmNetworkNATConnName = "{0}_NatConnection" -f $vmNetworkName

#NAT, Gateway and External IP Address Pool Commands$gatewayDevice = Get-SCNetworkGateway -Name $vmGWServiceName$VmNetworkGateway = Add-SCVMNetworkGateway -Name $vmNetworkGwName -EnableBGP $false `    -NetworkGateway $gatewayDevice -VMNetwork $vmNetwork `    -OnBehalfOfUser $User -OnBehalfOfUserRole $OwnerUserRoleObj$externalIpPoolVar = Get-SCStaticIPAddressPool -Name $vmExtStaticIPAddyPoolName$natConnection = Add-SCNATConnection -Name $vmNetworkNATConnName `    -VMNetworkGateway $VmNetworkGateway -ExternalIPPool $externalIpPoolVar `    -OnBehalfOfUser $User -OnBehalfOfUserRole $OwnerUserRoleObj

7 The New World of Tenant Provisioning

Page 11: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

012013014015

Note     Many other options are available, these are just the most common for a given scenario. The simple way to keep adding to this script is to make modifications in VMM, capture the generated script(s) and work the new portions in to the existing script.

Also Note     While the Add-SCVMNetworkGateway and Add-SCNATConnection commands do allow for -OnBehalfOfUser and -OnBehalfOfUserRole the user and user role specified may not have the necessary permissions to complete the operation (likely to the Gateway). The command execution may fail with a “You do not have permission to access one or more of the objects required by this operation.” error message. In this case, you may want to consider granting that access, or forgoing the “OnBehalfOf” for these two commands.

Calling the Create-VMNetwork PowerShell workflow

The following is a very basic example for calling this workflow:

001002003004005006

$VMMServer = "MY_VMM_SERVER" $UserRole = "USER_ROLE" $CloudName = "My Tenant Cloud" $LogicalNetworkName = "Contoso Logical Network" Create-VMNetwork -VmmServerName $VMMServer -OwnerUserRoleName $UserRole.Name `    -CloudName $CloudName -LogicalNetworkName $LogicalNetworkName

Again, there are lots of options here, choose the one that makes sense for your deployment. And I am not going to dive into the details for this example, but obviously you can leverage alternate objects/variables to collect/pass the parameter data within this call (as it is a 1:1 Tenant Admin User Role:VMNetwork in this example where Tenant Admin User Role = User + Subscription to a Plan).

8 The New World of Tenant Provisioning

Page 12: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Why go directly against VMM, as opposed to leveraging the WAP Tenant API?

For two reasons, really – First, I wanted to highlight and leverage existing known-good and well-used scripts; Second, the only available and published documentation / examples on the VM Network API are written in C#, not PowerShell.URL: http://msdn.microsoft.com/en-us/library/dn765986.aspx.

So, the above script is what we have been using on my team in our Demo/Test/Dev environment for months now. Also, one might argue that Network belongs to Fabric Management, which in turn belongs in VMM. Either way, based on what I could find, VMM is your [current] best bet.

Automated Active Directory VMRole Deployment

The OptionsIn fact, this is another great time to illustrate this in image form, for these two personas:

Note     These options are the same for any Automated VMRole Deployment, Active Directory happens to be the first one to be deployed, so it gets all the attention.

The ProcessI believe it is important for everyone to understand the current step-by-step process necessary to automatically deploy a VMRole via PowerShell against the available endpoints. It will let you appreciate the script that much more.

1. Generate the Gallery Item VMRole Reference URI (based on Subscription ID and Tenant Portal Address)

2. Invoke-WebRequest to Get the Gallery Item VMRole Reference (portion of the Gallery Item VMRole Resource Definition (ResDef) URI specific to the Gallery Item VMRole, based on the Gallery Item VMRole Name and data returned from Step #1)

9 The New World of Tenant Provisioning

Page 13: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

3. Generate the Gallery Item VMRole ResDef URI (based on data returned from Step #2)

4. Invoke-WebRequest to Get the Gallery Item VMRole ResDef (based on the URI from Step #3, data returned in JSON)

5. Convert (Deserialize) the returned ResDef JSON to a 'System.Collections.Generic.Dictionary[String,Object]

6. Create the Gallery Item VMRole Parameter Hashtable (based on custom variable data)

7. Convert the Gallery Item VMRole Parameter Hashtable to JSON 8. Create the Gallery Item VMRole Resource Definition

Configuration (ResDefConfig) 'System.Collections.Generic.Dictionary[String,Object]' (based on converted Gallery Item VMRole Parameter data (JSON) and Version information)

9. Create the Gallery Item VMRole Payload Hashtable (based on custom variable data, Gallery Item VMRole ResDef and ResDefConfig Dictionary Objects)

10. Convert the Gallery Item VMRole Payload Hashtable to JSON 11. Verify/Create Cloud Service Name (based on custom variable

data) 12. Generate the Gallery Item VMRole Deployment URI (based on

Subscription ID, Tenant Portal Address, and Cloud Service Name) 13. Invoke-WebRequest to Post the Gallery Item VMRole Payload

JSON (based on the URI from Step #14)

Step #11 (Cloud Service Creation/Verification) has several Sub-Steps:

1. Generate the Cloud Service URI (based on Subscription ID and Tenant Portal Address)

2. Invoke-WebRequest to Get the Cloud Service Data and verify if Cloud Service already exists (based on the URI from Sub-Step #1)

3. If exists, Output Cloud Service Name 4. If notexists, Create the Cloud Service Parameter Hashtable

(based on custom variable data) 5. Convert the Cloud Service Parameter Hashtable to JSON 6. Invoke-WebRequest to Post the Cloud Service JSON (based on

the URI from Sub-Step #1) 7. Once created, Output Cloud Service Name

Some people like images better, so here is one that represents the text above:

10 The New World of Tenant Provisioning

Page 14: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

So, if you were counting, that is…

4 URIs Dynamically Generated 3 Invoke-WebRequest GETs (for ResDef information) 4 Conversions (1 from JSON, 3 to JSON) 3 Hashtables Created 2 'System.Collections.Generic.Dictionary[String,Object]' 1 Cloud Service Creation (or reference to an existing Cloud

Service) 2 Invoke-WebRequest POSTs (1 for the Cloud Service Creation, 1

for the VMRole Deployment)

The magic here really exists in handling the data from JSON to Dictionary, Hashtable to JSON, etc. In fact, as you will see in the final script, JSON is the preferred method for data storage and transfer between sections of the script (from InlineScript to InlineScript and workflow to workflow).As a reference, be sure to review the following TechNet Article: Windows Azure Pack VMRoles Tenant API

11 The New World of Tenant Provisioning

Page 15: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Even More Magic – Bearer TokensI realize I keep using this word to emphasize technical significance, but when I find something so useful and so “simple”, I label it as such. That said, there is a CRITICAL piece in this process that HAS to be pointed out specifically:Get and Usage of the WAP MgmtSvcToken

I mention it in passing above, but this really makes everything work from a “Service Administrator leveraging the WAP Tenant API (non-public)” perspective.Here is the TechNet Library Article on the WAP command used to retrieve the token: Get-MgmtSvcToken

Here is the snippet of script (you will see it within the larger script below) where the token is retrieved from WAP, and then placed in a $Headers Hashtable, along with the identity of the User (essentially the WAP Tenant API’s version of “OnBehalfOf”):

001002003004005006007008009

$AdminURI = "https://" + $Using:WAPServer + ":30004"$AuthSite = "https://" + $Using:WAPServer + ":30072"$ClientRealm = "http://azureservices/AdminSite"$token = Get-MgmtSvcToken -Type Windows -AuthenticationSite $AuthSite `    -ClientRealm $ClientRealm -DisableCertificateValidation

$Headers = @{    Authorization = "Bearer $token"    "x-ms-principal-id" = $Using:UserID }

Note     This $Headers Hashtable gets reused over and over, each time an Invoke-WebRequest is made against the WAP Tenant API (non-Public). In fact, this bit of script is the only reason the InlineScript is leveraged, remoting to the WAP Admin Server – the rest of the calls are 100% Invoke-WebRequests and do not require the WAP Cmdlet. It is also important to note, this functionality is not restricted to VM Clouds, but can be leveraged for WAP Tenant API (non-public) calls, in general.

The Scripts

12 The New World of Tenant Provisioning

Page 16: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Based on the various options listed above, I am going to choose a [hopefully] winning combination that will satisfy the masses. Here goes…Colonel Mustard In The Study (With A Candlestick)

Oh wait - wrong combination!Service Administrator in SMA (with the WAP Tenant API Only)That’s better!So, what does this mean?

Service Administrator – The persona the script will be executed from and written for

in SMA – Service Management Automation, the PowerShell workflow engine in WAP (the very same thing that will automatically Create a VM Network “OnBehalfOf” a User Role, as described above)

(with the WAP Tenant API Only) – Because the script is executed from the Service Admin persona, there are a couple options, one is a mix of WAP Tenant API and VMM Cmdlet calls, the other is purely WAP Tenant API calls (no direct VMM commands used). Going with the WAP Tenant API Only option, keeps the script a bit more simple, and allows you to call the VMRole Deployments in the same way the Tenant Portal calls them. This means you can leverage the MicrosoftCompute.VMRole SPF event for monitoring and notification if desired (again, see the following blog post: Automation–Monitoring and Notifying in Windows Azure Pack with SMA for more information).

As you know, using SMA means using PowerShell workflow. It is a bit more complex than just “regular PowerShell”, but many liberties can be taken when leveraging the InlineScript functionality. Taking liberties, making my life easier, and built-in PowerShell Remoting are the three main reasons I chose to go with InlineScript in these examples. I am not opposed to other methods, this is just the one I chose.

The overall structure of the SMA Runbooks

1. Subscription-Create-Dispatcher: Top Tier Dispatch Runbook; hooked directly to the SPF event call; captures SPF event Data (Subscription and User info, etc.); used to decide which Subscription to act against, and which User to act for; calls numerous other Sub-Runbooks (including the one(s) for Tenant Virtual Network Creation and VMRole Deployments – this is where multiple VMRole Deployments can be called at once)

2. Deploy-TenantVMRole: Middle Tier Sub-Runbook; called by Dispatch Runbook; collects, parses and organizes deployment data from input parameter and variable data; calls Lowest Tier Sub-Runbook with specific deployment criteria

3. Deploy-VMRole: Lowest Tier Sub-Runbook; called by Middle Tier Sub-Runbook; collects and uses input parameter data; executes all required VMRole Deployment calls (this is where some of the

13 The New World of Tenant Provisioning

Page 17: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

“options” come in – for example, instead of executing only against the WAP Tenant API, the actual VMRole Deployment could execute the required VMM Cmdlet command (Add-CloudResource)

And to help with the overall visualization as well as where these SMA Runbooks fit in the all-up process, here is another image:

Did someone say Scripts?

Yeah, yeah. I am getting there. Remember, it is not only about the “code”, but also how that “code” came to be. Or at least that is my reasoning for taking you on this journey.

Deploy a Gallery Item VMRoleI am going to start with the Lowest Tier Sub-Runbook (Deploy-VMRole), and work up.

14 The New World of Tenant Provisioning

Page 18: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

The following PowerShell workflow script (Deploy-VMRole) will deploy a WAP Gallery Item VMRole with the following settings (with the WAP Tenant API Only):

WAP Server: <Name of WAP Admin Server defined with parameter used by InlineScript Remoting and by WAP Admin PowerShell Cmdlet>

Credentials: <PSCredential defined with parameter used by InlineScript Remoting>

Tenant Portal Address: <FQDN of the WAP Tenant Portal Server defined with parameter used to generate URIs for Invoke-WebRequest API Calls to WAP Tenant API>

Subscription ID: <Subscription ID for the User for whom the VMRoles will be deployed, defined with parameter>

User ID: <User ID of the User for whom the VMRoles will be deployed, defined with parameter>

Gallery Item Name: <Partial or Full Name of the Gallery Item VMRole to be Deployed, defined with parameter, used to match the Gallery Item Reference Data to generate the Gallery Item ResDef URI>

Gallery Item Version: <Version of the Gallery Item VMRole to be Deployed, defined with parameter, used to identify correct version of the Gallery Item VMRole>

ResDefConfig JSON: <Resource Definition Configuration data (in JSON format), defined with parameter, used to satisfy the ResDef, part of the Gallery Item VMRole Payload>

Cloud Service Name: <Name of the Cloud Service, defined with parameter, used in the Gallery Item VMRole Deployment>

VMRole Name: <Name of the VMRole to be Deployed, defined with parameter, part of the Gallery Item VMRole Payload>

Note     Each of these parameters are leveraged throughout the Deploy-VMRole workflow and are configured for maximum re-use and flexibility. The intention of this Low Tier Sub-Runbook is to remain as generic as possible. Specific parameter setting occurs at the Top and Middle Tier Runbooks.

Example PowerShell workflow script for Deploy-VMRole001002003004005006007008009010011012013

workflow Deploy-VMRole{    param    (        [string]$WAPServer,        [PSCredential]$Creds,        [string]$TenantPortalAddress,        [string]$SubscriptionID,        [string]$UserID,        [string]$GalleryItemName,        [string]$GIVersion,        [string]$ResDefConfigJSON,        [string]$CloudServiceName,        [string]$VMRoleName    )

    $VMRole = InlineScript {

        $AdminURI = "https://" + $Using:WAPServer + ":30004"        $AuthSite = "https://" + $Using:WAPServer + ":30072"        $ClientRealm = "http://azureservices/AdminSite"        $token = Get-MgmtSvcToken -Type Windows -AuthenticationSite $AuthSite -ClientRealm $ClientRealm -DisableCertificateValidation

        $Headers = @{            Authorization = "Bearer $token"            "x-ms-principal-id" = $Using:UserID }

15 The New World of Tenant Provisioning

Page 19: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

01401501601701801902002102202302402502602702802903003103203303403503603703803904004104204304404504604704804905005105205305405505605705805906006

        # Get Gallery Item Reference        $GIReferenceUri = "https://{0}:30005/{1}/Gallery/GalleryItems/$/MicrosoftCompute.VMRoleGalleryItem?api-version=2013-03" -f $Using:TenantPortalAddress,$Using:SubscriptionID        $GIReferenceData = [xml](Invoke-WebRequest -Uri $GIReferenceUri -Headers $Headers -UseBasicParsing | Select-Object -ExpandProperty Content)        $GalleryItemREF = $GIReferenceData.feed.entry.content.properties.resourcedefinitionUrl | ? {$_ -match $Using:GalleryItemName}

        # Get Gallery Item Resource Definition        $GIResDEFUri = "https://{0}:30005/{1}/{2}/?api-version=2013-03" -f $Using:TenantPortalAddress,$Using:SubscriptionID,$GalleryItemREF        $GIResourceDEFJSON = Invoke-WebRequest -Uri $GIResDEFUri -Headers $Headers -UseBasicParsing | Select-Object -ExpandProperty Content               #Convert ResDef JSON to Dictionary        [System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions") | Out-Null        $JSSerializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer        $ResDef = $JSSerializer.DeserializeObject($GIResourceDEFJSON)

        #Add ResDefConfig JSON to Dictionary        $ResDefConfig = New-Object 'System.Collections.Generic.Dictionary[String,Object]'        $ResDefConfig.Add("Version",$Using:GIVersion)        $ResDefConfig.Add("ParameterValues",$Using:ResDefConfigJSON)

        # Set Gallery Item Payload Variables        $GISubstate = $null        $GILabel = $Using:VMRoleName        $GIName = $Using:VMRoleName        $GIProvisioningState = $null        $GIInstanceView = $null

        # Set Gallery Item Payload Info        $GIPayload = @{            "InstanceView" = $GIInstanceView            "Substate" = $GISubstate            "Name" = $GIName            "Label" = $GILabel            "ProvisioningState" = $GIProvisioningState            "ResourceConfiguration" = $ResDefConfig            "ResourceDefinition" = $ResDef            }

        # Convert Gallery Item Payload Info To JSON        $GIPayloadJSON = ConvertTo-Json $GIPayload -Depth 7

        # Get Cloud Services        $CloudServicesUri = "https://{0}:30005/{1}/CloudServices?api-version=2013-03" -f $Using:TenantPortalAddress,$Using:SubscriptionID        $CloudServicesData = [xml](Invoke-WebRequest -Uri $CloudServicesUri -Headers $Headers -UseBasicParsing | Select-Object -ExpandProperty Content)        $CloudService = $CloudServicesData.feed.entry.content.properties.Name | ? {$_ -match $Using:CloudServiceName}        if (!$CloudService) {            # Set Cloud Service Configuration            $CloudServiceConfig = @{                "Name" = $Using:CloudServiceName                "Label" = $Using:CloudServiceName                }

            # Convert Cloud Service Configuration To JSON            $CloudServiceConfigJSON = ConvertTo-Json $CloudServiceConfig

            $CloudServicesData = [xml](Invoke-WebRequest -Uri $CloudServicesUri -Headers $Headers -Method Post -Body $CloudServiceConfigJSON -ContentType "application/json" -UseBasicParsing)            $CloudService = $CloudServicesData.entry.content.properties.Name | ? {$_ -match $Using:CloudServiceName}        }

        # Set Gallery Item VMRole Deploy URI        $GIDeployUri = "https://{0}:30005/{1}/CloudServices/{2}/Resources/MicrosoftCompute/VMRoles/?api-version=2013-03" -f $Using:TenantPortalAddress,$Using:SubscriptionID,$CloudService

        # Deploy Gallery Item VMRole        $VMRoleDeployed = Invoke-WebRequest -Uri $GIDeployUri -Headers $Headers -Method Post -Body $GIPayloadJSON -ContentType "application/json" -UseBasicParsing

        Return $VMRoleDeployed

    } -PSComputerName $WAPServer -PSCredential $Creds$VMRole}

16 The New World of Tenant Provisioning

Page 20: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

1062063064065066067068069070071072073074075076077078079080081082083084085086087088089090091092093094095096097098

Note     There are a ton of nuances within this example workflow. It is because of this, I outlined The Process above. In fact, this example workflow includes the following process steps: 1-5, 8-13 and all Cloud Service Creation sub-steps. Steps 6 and 7 occur in the Middle Tier Sub-Runbook.

Calling the Deploy-VMRole PowerShell workflow

17 The New World of Tenant Provisioning

Page 21: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

The following PowerShell workflow script (Deploy-TenantVMRole) will call the Deploy-VMRole workflow with the following settings:

WAP Server: <Name of WAP Admin Server, defined by SMA Variable>

Credentials: <PSCredential, defined by SMA Variable> Tenant Portal Address: <FQDN of the WAP Tenant Portal Server,

defined by SMA Variable> Subscription ID: <Subscription ID for the User for whom the

VMRoles will be deployed, defined by parsing the $OwnerUserRole parameter>

User ID: <User ID of the User for whom the VMRoles will be deployed, defined by parsing the $OwnerUserRole parameter>

Gallery Item Name: <Partial or Full Name of the Gallery Item VMRole to be Deployed, defined by parsing the $GalleryItemToDeploy parameter>

Gallery Item Version: <Version of the Gallery Item VMRole to be Deployed, defined by parsing the $GalleryItemToDeploy parameter>

Cloud Service Name: <Name of the Cloud Service, generated by combining hardcoded custom variable data and $SubscriptionID variable>

OS Disk: <Name of the Default OS Disk to be used in the Gallery Item VMRole Deployment, defined by SMA Variable>

Password: <Password used in the Gallery Item VMRole Deployment, defined by SMA Variable>

ResDefConfig JSON: <Resource Definition Configuration data (in JSON format), defined by numerous parameters/variables, contains common and Gallery Item VMRole specific data>

Note     You may keep these example settings, or modify to fit your deployment specifications. Each of these parameters/variables are leveraged in the Deploy-VMRole workflow call and are configured for maximum re-use and flexibility. The intention of this Middle Tier Sub-Runbook is to balance common and Gallery Item VMRole specific data so that the line between them is clear and updates are simple (as the number of Gallery Item VMRoles in your environment grows). Even more specific parameter settings occur in the Top Tier Runbook.

Example PowerShell workflow script for Deploy-TenantVMRole

001002003004005006007

workflow Deploy-TenantVMRole{    param    (        [string]$OwnerUserRole,        [string]$GalleryItemToDeploy,        [string]$VMRoleName,        [string]$VMRoleNamePattern,        [string]$VMRoleSize    )        #Define Variables    $WAPServer = Get-AutomationVariable -Name 'WAP Admin Server'    $Creds = Get-AutomationPSCredential -Name 'PSCredential Name'

18 The New World of Tenant Provisioning

Page 22: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041

    $TenantPortalAddress = Get-AutomationVariable -Name 'WAP Tenant Server FQDN'    $SubscriptionID = $OwnerUserRole.Split("_")[1]    $UserID = $OwnerUserRole.Split("_")[0]    $GalleryItemName = $GalleryItemToDeploy.Split(";")[0]    $GIVersion = $GalleryItemToDeploy.Split(";")[1]    $CloudServiceName = "CloudService-4-{0}" -f $SubscriptionID    $OSDisk = Get-AutomationVariable -Name 'Default VMRole OS Disk'    $Password = Get-AutomationVariable -Name 'Password'        # Create Gallery Item Parameter Hashtable (for Common Data)    $GIParamList = @{        VMRoleVMSize = $VMRoleSize        VMRoleOSVirtualHardDiskImage = $OSDisk        VMRoleAdminCredential = "administrator:{0}" -f $Password        VMRoleTimeZone = "Pacific Standard Time"        VMRoleComputerNamePattern = $VMRoleNamePattern        VMRoleNetworkRef = "Tenant Network ({0})" -f $UserID        }

    # Add to Gallery Item Parameter Hashtable (for GI Specific Data)    if ($GalleryItemName -eq "DomainController")    {        $GIParamList += @{DomainControllerWindows2012DomainDNSName = $UserID.Split("@")[1]}         $GIParamList += @{DomainControllerWindows2012DomainNETBIOSName = ($UserID.Split("@")[1]).Split(".")[0]}        $GIParamList += @{DomainControllerWindows2012SafeModeAdminPassword = $Password}    }        # Convert Gallery Item Parameter Hash To JSON    $ResDefConfigJSON = ConvertTo-Json $GIParamList        Deploy-VMRole -WAPServer $WAPServer -creds $Creds -TenantPortalAddress $TenantPortalAddress `        -SubscriptionID $SubscriptionID -UserID $UserID -GalleryItemName $GalleryItemName `        -GIVersion $GIVersion -ResDefConfigJSON $ResDefConfigJSON -CloudServiceName $CloudServiceName `        -VMRoleName $VMRoleName}

19 The New World of Tenant Provisioning

Page 23: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

042043044045046047048049

Did you miss it?

Up to this point, you have been inundated with “generic” workflow examples to Deploy any Gallery Item VMRole. So, you may have actually missed where this went from “generic” to “specific”. If you did, look up at the Deploy-TenantVMRole workflow script again, and checkout lines 34-40ish. For this Middle Tier Sub-Runbook, that is the extent of the “specific”. Believe me, I would have loved to make this and the Lowest Tier Sub-Runbook 100% Generic, but it is just not possible. More about this, and the decisions I made are in the note below.Note     The Gallery Item VMRole specific data (as it relates to the other Gallery Item VMRoles in this document, and from the Building Clouds Blog Gallery) is kept in a separate section (lines 34-40ish above) and is surrounded by “if” logic. The intention of this section is to logically store the Gallery Item VMRole specific data by $GalleryItemName. I put quite a bit of thought on where the best place for this “unique” data should live within these example workflows, as well as more dynamic ways to process it – this happens to be where it landed and what it looks like. And obviously, this will not work for every possible VMRole created. But it is one idea/implementation that has worked for my team’s deployment scenario. Oh, and before I forget, this is the portion of the examples where Steps 6 and 7 of The Process take place.

Calling the Deploy-TenantVMRole PowerShell workflow

The following PowerShell workflow script (Subscription-Create-Dispatcher) will call the Deploy-TenantVMRole workflow with the following settings:

Gallery Item To Deploy: <Concatenated string made up of the Gallery Item Name (full or partial) and Gallery Item Version in GalleryItemName:1.0.0.0 format, defined by custom data>

Owner User Role: <Concatenated string made up of the User ID (email address) and Subscription ID (GUID) in

20 The New World of Tenant Provisioning

Page 24: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

[email protected]_SUBSC_RIPTION_GUID_STRING, defined by SPF event Data stored in the $resourceObject input variable>

VMRole Name: <Name of the VMRole to be Deployed (will be how the VMRole is seen in the Tenant Portal), defined by custom data>

VMRole Name Pattern: <Name Pattern of the VM to be Deployed (will be how the VM is named within the hypervisor) in NN## format, defined by custom data>

VMRole Size: <Size of the VMRole to be Deployed, restricted to available VMM Hardware Profile/Gallery Item VMRole definitions, defined by custom data>

Note     The data entered here is completely customizable and should fit your deployment specifications. The intention of this Top Tier Runbook is to set Gallery Item VMRole specific variables and parameters to be passed on to the much more generic Middle and Lowest Tier Sub-Runbooks. In fact, this Top Tier Runbook is where the Tenant configuration is built out:

Virtual Network Creation Multiple concurrent (and/or dependent) Gallery Item VMRole

Deployments Job Monitoring Notifications Etc.

Remember, as the Top Tier Runbook, it is the one called by the Subscription.Create WAP/SPF event, configured in the VM Clouds Resource Provider:

It is the main “hook” for the Tenant Provisioning Process of “Subscribe to a Plan, Get a Fully Deployed Set of Collaborative Workloads”.

Example PowerShell workflow script for Subscribe-Create-Dispatcher

001002003004005006007008009010011012

workflow Subscription-Create-Dispatcher{    param    (        [object]$resourceObject    )

    if ($resourceObject.AdminID.Length -gt 27) { $AdminId = $AdminId.SubString(0,27) } else { $AdminId = $resourceObject.AdminId }    $OwnerUserRole = $AdminId + "_" + $resourceObject.SubscriptionID    $SubscriptionName = $resourceObject.SubscriptionName        $VMMServer = Get-AutomationVariable -Name 'VMM Server'

21 The New World of Tenant Provisioning

Page 25: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

013014015016017018019020021022023024025026027028029030031032

    $LogicalNetworkName = Get-AutomationVariable -Name 'Default VMM Logical Network'    $PSEmailServer = Get-AutomationVariable -Name 'SMTP Server'    $PSEmailFrom = Get-AutomationVariable -Name 'SMTP From Email'    $PSEmailCC = Get-AutomationVariable -Name 'PSEmailCC'        if ($SubscriptionName -eq "Collaboration Workloads")    {        $CloudName = "Tenant Cloud"        Create-VMNetwork -VmmServerName $VMMServer -OwnerUserRole $OwnerUserRole -CloudName $CloudName -LogicalNetworkName $LogicalNetworkName                Send-SMTPNotification -SendNotificationType "Plans" -PSEmailFrom $PSEmailFrom -PSEmailTo $AdminId `            -PSEmailServer $PSEmailServer -PSEmailCC $PSEmailCC -WorkloadName $SubscriptionName        $SubscriptionName + " Plan Selected"                "Deploying Active Directory"        Deploy-TenantVMRole -GalleryItemToDeploy "DomainController;1.0.0.0" `            -OwnerUserRole $OwnerUserRole -VMRoleName "ActiveDirectory" `            -VMRoleNamePattern "DC##" -VMRoleSize "ExtraSmall"    }}

Note     This example is exactly what we have been using on my team in our Demo/Test/Dev environment. As you can see, it includes more than just a call to the Deploy-TenantVMRole workflow. In fact, it also includes:

Extraction of SPF event data from the $resourceObject input variable

Example generation of the $OwnerUserRole string Usage of SMA Variables Logic for Subscription dispatching based on Subscription Name (one

example provided) Invocation of the Create-VMNetwork workflow (to create the

Tenant Virtual Network described above) Invocation of the Send-SMTPNotification workflow (to send email

notifications to the user about post-subscription activities) - For more information (and a specific example) about how the Send-SMTPNotification workflow, see the following blog post: Automation–Monitoring and Notifying in Windows Azure Pack with SMA

And finally, Invocation of the Deploy-TenantVMRole workflow (with Gallery Item VMRole specific data)

By the way - I realize that some of the direct text output and use of hardcoded values could be better served in Write-Verbose commands and usage of variables (respectively), but for our environment, and for this example, this is what I went with. That said, you may keep these example settings, or modify to fit your deployment specifications.

Oh, and if you are wondering about Job Monitoring, our environment has that too – it just so happens to be hooked to a different Top Level Dispatch Runbook: VMRole-Create-Dispatcher. And because the Deploy-VMRole workflow leverages the same exact method for VMRole creation as the Tenant Portal, the WAP/SPF event for MicrosoftCompute.VMRole works the same:

22 The New World of Tenant Provisioning

Page 26: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

So, for fun…

Example PowerShell workflow script for VMRole-Create-Dispatcher

001002003004005006007008009010011012013014015016017018019020021

workflow VMRole-Create-Dispatcher{    param    (        [object]$resourceObject    )    $VMRoleOwner = $resourceObject.Owner    $VMRoleName = $resourceObject.Name    $SCJobID = $resourceObject.MostRecentTask.ID    $PSEmailServer = Get-AutomationVariable -Name 'SMTP Server'    $PSEmailFrom = Get-AutomationVariable -Name 'SMTP From Email'    $PSEmailCC = Get-AutomationVariable -Name 'PSEmailCC'        Send-SMTPNotification -SendNotificationType "Workloads" -PSEmailFrom $PSEmailFrom ` -PSEmailTo $VMRoleOwner -PSEmailServer $PSEmailServer -PSEmailCC $PSEmailCC -WorkloadName $VMRoleName     "Job ID ($SCJobID) is being monitored"    $VMRoleDeploy = Monitor-VMMJobStatus -SleepDuration 300 -SCJobID $SCJobID -OutputStatus $false    "Deploy of $VMRoleName : $VMRoleDeploy"    Send-SMTPNotification -JobState $VMRoleDeploy -SendNotificationType "Workloads-Complete" -PSEmailFrom $PSEmailFrom ` -PSEmailTo $VMRoleOwner -PSEmailServer $PSEmailServer -PSEmailCC $PSEmailCC -WorkloadName $VMRoleName      }

The combination of Monitoring and Notifications allow for the creation of emails like:

BONUS - Example VMM PowerShell for Gallery Item VMRole Deployment!Oh, alright…Here is another example script.

23 The New World of Tenant Provisioning

Page 27: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

What does it do?

It is the portion of the Deploy-VMRole required if you wanted to leverage the VMM Cmdlet command Add-CloudResource instead of going WAP Tenant API OnlyNote     If you want to go this route, this example script replaces the existing script portion within the Deploy-VMRole starting around line 45, right through to the end (before the workflow’s end bracket).

Sound interesting?

Alternate Example PowerShell workflow script for a portion of the Deploy-VMRole

001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030

$GIVMRole = InlineScript {            #Convert ResDef JSON to Dictionary    [System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions") | Out-Null    $JSSerializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer    $ResDef = $JSSerializer.DeserializeObject($Using:ResDefJSON)

    #Add ResDefConfig JSON to Dictionary    $ResDefConfig = New-Object 'System.Collections.Generic.Dictionary[String,Object]'    $ResDefConfig.Add("Version",$Using:GIVersion)    $ResDefConfig.Add("ParameterValues",$Using:ResDefConfigJSON)

    Get-SCVMMServer -ComputerName $Using:VMMServer -ForOnBehalfOf | Out-Null    $OwnerUserRole = Get-SCUserRole | ? {$_.Name -match $Using:UserID}

    #Create a CloudService    $Cloud = Get-SCCloud -Name $Using:CloudName -OnBehalfOfUser $Using:UserID -OnBehalfofUserRole $OwnerUserRole    $CloudSevice = Get-CloudService -Name $Using:CloudServiceName  -OnBehalfOfUser $Using:UserID -OnBehalfofUserRole $OwnerUserRole    if (!$CloudSevice) {        $CloudSevice = New-CloudService -Cloud $Cloud -Name $Using:CloudServiceName -OnBehalfOfUser $Using:UserID -OnBehalfofUserRole $OwnerUserRole    }

    $CloudResource = Add-CloudResource -CloudService $CloudSevice -ResourceDefinition $ResDef -ResourceName $Using:VMRoleName `        -OnBehalfOfUser $Using:UserID -OnBehalfofUserRole $OwnerUserRole -ResourceConfiguration $ResDefConfig -RunREST

    Return $CloudResource

} -PSComputerName $VMMServer -PSCredential $Creds

$GIVMRole

Note     Again, this is still example workflow script to be executed as the Service Admin, this time against VMM directly, instead of leveraging the WAP Tenant API. You will see that I leveraged a second InlineScript, this time to connect to the VMM Server (as the WAP Tenant API calls that come before it execute via InlineScript connected to the WAP Server). You will also see that we are still leveraging “OnBehalfOf” functionality for the VMM commands, this is required if you want proper Tenant ownership of the deployed resources.

The biggest thing to know about the Add-CloudResource command is that the -ResourceDefinition and -ResourceConfiguration parameters require Dictionary Objects. This is why I have both the ResDef and ResDefConfig convert/deserialization steps in this section. In fact, this portion of the script includes steps 8-13 and all Cloud Service Creation sub-steps from The Process described above.

24 The New World of Tenant Provisioning

Page 28: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Finally, it is worth restating - JSON is the preferred method for data storage and transfer between sections of the script (from InlineScript to InlineScript and workflow to workflow).

Use CasesBut wait, WHY would I want to do this?

Here are some use cases (all from the Service Admin persona):

Use Case 1: Provision a nearly complete environment to your Tenants/End Users at the click of a self-service button (Subscription to a Plan)

Use Case 2: Enable Gallery Item VMRole deployment from a custom self-service portal, feeding the SMA Runbooks with more dynamic parameter data

Use Case 3: Integrate Gallery Item VMRole deployment with an existing customer facing interface

Use Case 4: Develop and Execute SMA Runbooks (potential to take in Parameters during execution) to deliver Gallery Item VMRoles on-demand

25 The New World of Tenant Provisioning

Page 29: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Automated Deployment of the Identity Workload as a Tenant AdminI realize the heading of this section is very similar to the last, and there is very good reason for that. Though they look similar, they are different. Different personas; different scripts; different context. The scope of this section is illustrated by the portion of the image with the red outline:

To clear things up, let’s expand on the title for this section, (now with more sub-title!):

Automated Deployment of the Identity Workload as a Tenant Admin

(Active Directory VMRole; from the Tenant Admin Persona)

The last section of this document was all about deployment as the Service Administrator persona. Now, in this section, it is all about deployment as the Tenant Administrator.I think it is time for another quick rehash (with image):

26 The New World of Tenant Provisioning

Page 30: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

In the above image, we see my view of these two personas, as well as what we will be getting into for this post (the first two bullets in the box on the right).

The OptionsHow about another image?

This time, to visualize the high-level process for the Tenant Admin:

27 The New World of Tenant Provisioning

Page 31: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

So, as you can see, the Tenant Admin has options.Note     Automatically adding the Isolated Tenant Virtual Network (Isolated Software Defined Network (SDN)) is completely optional, as the Service Admin can simply recommend that the Tenant Admin manually create Virtual Networks from the Tenant Portal before deploying VMRoles.

Reminder     These options are the same for any VMRole Deployment, Active Directory happens to be the first one to be deployed, so it gets all the attention.

The ProcessRemember that multi-step process I described in the last section?

Well, it is basically the same.

28 The New World of Tenant Provisioning

Page 32: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

So, to save you from going back and forth, here is the representative image for “The Process”:

What’s the difference?

Primarily, it is the Web Service Endpoint PORT and Authorization method.As a Service Admin, you can leverage Bearer Token authorization and make WS calls against the Tenant API (non-Public), Port 30005 As a Tenant Admin, you leverage Certificates and make WS calls against the Public Tenant API, Port 30006 In fact, if you are familiar with Automating Windows Azure with PowerShell, the pre-requisite process has a very similar look and feel.Care to venture a guess what we leverage to setup/use the Certificate?

The Windows Azure PowerShell Module (It is one of the options anyway.)

29 The New World of Tenant Provisioning

Page 33: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

That’s right. The very same – and if you haven’t checked it out, or downloaded the latest version, you may have missed all the “new-ish” commands that contain *-WAPack*

Which is a great segue to…

The Pre-Requisites1. Valid Account and Subscription to a Plan within WAP (have the ability

to login to the WAP Tenant Portal and provision Gallery Items (VMRoles)):

2. The latest Windows Azure PowerShell module (contains the latest *-WAPack* Commands):

3. Ability to Execute Windows Azure PowerShell Commands 4. Creation and Usage of a Management Certificate (derived from WAP

Publish Settings File – see the Pre-Requisite Setup steps below)

30 The New World of Tenant Provisioning

Page 34: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

The Pre-Requisite Setup

1. Download and Install the Windows Azure PowerShell Commands 2. Get the Published Settings File for your Subscription – Navigate to

your version of the following URL: https://tenant.portal.com:30081/publishsettings

This will prompt to download the file locally – My recommendation is to download to the machine where the PowerShell Scripts will be executed.

Note     If the target portal leverages ADFS, do not include the port (30081) in the address while attempting to retrieve the .publishsettings file. At least this is what I experienced between the two environments we have, one without ADFS (required port in URL), and one with ADFS (port not used in URL).

(Example Path: C:\LocalPath\SubscriptionName-MM-d-YYYY-credentials.publishsettings)

3. Open PowerShell and ensure the Windows Azure PowerShell module is loaded

4. Execute the following command (modify the command text based on the name and where the publishsettings file is located):

Import-WAPackPublishSettingsFile C:\WAP\Collaboration Workloads (Tenant Deployed)-3-11-2014-credentials.publishsettings

31 The New World of Tenant Provisioning

Page 35: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Note    These steps not only import the certificate into the Management Certificates section in the Tenant Portal:

But ALSO add it to the Certificate Store for the Current User:

Resulting in the following, when Get-WAPackSubscription is executed from PowerShell:

Reminder    The security best practice for the publishsettings file is to store it temporarily, and then delete it after the settings have been imported. A malicious user gaining access to the publishsettings file can edit, create, and delete your WAP resources.

So, there you go - All the theory and pre-requisites you can handle, right?

The good news…With these pre-requisites out of the way, we can now get on to the actual deployment script!

Active Directory Gallery Item VMRole Deployment as a Tenant Admin(Against the Public WAP API)

001002003004005006007

#region GetWAPConnectionData

# Get WAP Subscription Information$WAPSubscription = Get-WAPackSubscription

# Set Subscription$SubscriptionID = $WAPSubscription.SubscriptionId

32 The New World of Tenant Provisioning

Page 36: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054055056057058059060061062063064065066067068069070071072073074075076077078079080081082083084085086087088089090091092093094095096097098099100101102

# Get Management Certificate Info$CertThumb = $WAPSubscription.Certificate.Thumbprint$CertPath = "Cert:\CurrentUser\My\{0}" -f $CertThumb$Cert = Get-Item $CertPath

# Set Tenant Portal Address$TenantPortalAddress = $WAPSubscription.ServiceEndpoint.Host

# Set Port$Port = $WAPSubscription.ServiceEndpoint.Port

#endregion GetWAPConnectionData

#region SetVariables

# Set Gallery Item Name and Version for Match and Deploy$GalleryItemName = "DomainController"$GIVersion = "1.0.0.0"

# Set Common Gallery Item Parameters$UserID = "[email protected]"$VMRoleNetwork = "Tenant Network ({0})" -f $UserID$CloudServiceName = "CloudService-4-{0}" -f $SubscriptionID$VMRoleName = "ActiveDirectory"$VMRoleNamePattern = "DC##"$VMRoleSize = "ExtraSmall"$VMRoleTZ = "Pacific Standard Time"$OSDisk = "Windows Server 2012 Datacenter"$OSDiskVersion = "1.0.0.0"$Password = "Password"

#endregion SetVariables

#region GetResDef

# Get Gallery Item Reference$GIReferenceUri = "https://{0}:{1}/{2}/Gallery/GalleryItems/$/MicrosoftCompute.VMRoleGalleryItem?api-version=2013-03" -f $TenantPortalAddress,$Port,$SubscriptionID$GIReferenceData = [xml](Invoke-WebRequest -Certificate $Cert -Uri $GIReferenceUri | Select-Object -ExpandProperty Content)$GalleryItemREF = $GIReferenceData.feed.entry.content.properties.resourcedefinitionUrl | ? {$_ -match $GalleryItemName}

# Get Gallery Item Resource Definition$GIResDEFUri = "https://{0}:{1}/{2}/{3}/?api-version=2013-03" -f $TenantPortalAddress,$Port,$SubscriptionID,$GalleryItemREF$GIResourceDEFJSON = Invoke-WebRequest -Certificate $Cert -Uri $GIResDEFUri | Select-Object -ExpandProperty Content

#Convert ResDef JSON to Dictionary[System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions") | Out-Null$JSSerializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer$ResDef = $JSSerializer.DeserializeObject($GIResourceDEFJSON)

#endregion GetResDef

#region SetResDefConfig

# Create Gallery Item Parameter Hashtable (for Common Data)$GIParamList = @{    VMRoleVMSize = $VMRoleSize    VMRoleOSVirtualHardDiskImage = "{0}:{1}" -f $OSDisk,$OSDiskVersion    VMRoleAdminCredential = "administrator:{0}" -f $Password    VMRoleTimeZone = $VMRoleTZ    VMRoleComputerNamePattern = $VMRoleNamePattern    VMRoleNetworkRef = $VMRoleNetwork    }

# Add to Gallery Item Parameter Hashtable (for GI Specific Data)if ($GalleryItemName -eq "DomainController"){    $GIParamList += @{DomainControllerWindows2012DomainDNSName = $UserID.Split("@")[1]}     $GIParamList += @{DomainControllerWindows2012DomainNETBIOSName = ($UserID.Split("@")[1]).Split(".")[0]}    $GIParamList += @{DomainControllerWindows2012SafeModeAdminPassword = $Password}}    # Convert Gallery Item Parameter Hashtable To JSON$ResDefConfigJSON = ConvertTo-Json $GIParamList

#Add ResDefConfig JSON to Dictionary$ResDefConfig = New-Object 'System.Collections.Generic.Dictionary[String,Object]'$ResDefConfig.Add("Version",$GIVersion)$ResDefConfig.Add("ParameterValues",$ResDefConfigJSON)

#endregion SetResDefConfig

#region GenerateGIPayloadJSON

# Set Gallery Item Payload Variables$GISubstate = $null$GILabel = $VMRoleName$GIName = $VMRoleName$GIProvisioningState = $null$GIInstanceView = $null

# Set Gallery Item Payload Info$GIPayload = @{    "InstanceView" = $GIInstanceView    "Substate" = $GISubstate

33 The New World of Tenant Provisioning

Page 37: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146

    "Name" = $GIName    "Label" = $GILabel    "ProvisioningState" = $GIProvisioningState    "ResourceConfiguration" = $ResDefConfig    "ResourceDefinition" = $ResDef    }

# Convert Gallery Item Payload Info To JSON$GIPayloadJSON = ConvertTo-Json $GIPayload -Depth 7

#endregion GenerateGIPayloadJSON

#region GetOrSetCloudService

# Get Cloud Services$CloudServicesUri = "https://{0}:{1}/{2}/CloudServices?api-version=2013-03" -f $TenantPortalAddress,$Port,$SubscriptionID$CloudServicesData = [xml](Invoke-WebRequest -Uri $CloudServicesUri -Certificate $Cert | Select-Object -ExpandProperty Content)$CloudService = $CloudServicesData.feed.entry.content.properties.Name | ? {$_ -match $CloudServiceName}if (!$CloudService) {    # Set Cloud Service Configuration    $CloudServiceConfig = @{        "Name" = $CloudServiceName        "Label" = $CloudServiceName        }

    # Convert Cloud Service Configuration To JSON    $CloudServiceConfigJSON = ConvertTo-Json $CloudServiceConfig

    $CloudServicesData = [xml](Invoke-WebRequest -Uri $CloudServicesUri -Certificate $Cert -Method Post -Body $CloudServiceConfigJSON -ContentType "application/json")    $CloudService = $CloudServicesData.entry.content.properties.Name | ? {$_ -match $CloudServiceName}}

#endregion GetOrSetCloudService

#region DeployGIVMRole

# Set Gallery Item VMRole Deploy URI$GIDeployUri = "https://{0}:{1}/{2}/CloudServices/{3}/Resources/MicrosoftCompute/VMRoles/?api-version=2013-03" -f $TenantPortalAddress,$Port,$SubscriptionID,$CloudService

# Deploy Gallery Item VMRole$VMRoleDeployed = Invoke-WebRequest -Uri $GIDeployUri -Certificate $Cert -Method Post -Body $GIPayloadJSON -ContentType "application/json"$VMRoleDeployed

#endregion DeployGIVMRole

Note(s)     I have several notes about the above script. So I will list them here:

This is just an example script. It has been tested against our Demo/Test/Dev environment multiple

times. It absolutely requires the pre-requisites discussed above. And while

there are alternatives to getting the required variable data based on the Get-WAPackSubscription command, I have found this to be the most efficient/dynamic method.

The $TenantPortalAddress Variable may need to  be set to a specific string, rather than being extracted from the information available from the Get-WAPackSubscription command, specifically if the public portal address is different than the FQDN of WAP Admin Server.

If you are getting errors during deployment like, “Disk with Name (Windows Server 2012 Datacenter) and Version (1.0.0.0) not found while translating Resource Definition for cloud resource.” it is likely that the $OSDisk and/or $OSDiskVersion Variables have incorrect data. The Tenant API does not care so much for the actual OS Disk name, instead, it appears to require the Family Name of the OS Disk.

I chose to leave all the Variable settings within the script. These could very easily be presented as Script Parameters, and fed into the script to make it a bit more generic.

Just like the Service Admin example script, there is a portion of the Resource Definition Configuration (ResDefConfig) that is tied directly

34 The New World of Tenant Provisioning

Page 38: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

to the ResDef/ResDefExt for a given Gallery Item VMRole. When generating the Gallery Item Parameter Hashtable, I have separated the GI specific data from the common GI data. In most cases (especially for the Gallery Item VMRoles produced by my team), the only portion of the script that has to change per VMRole is this GI specific data (and, of course any specific Variable data).

This script (for the Tenant Admin) should look nearly identical to the script from Part 2 (for the Service Admin). This is by design, as I wanted to keep as many synergies in play as possible. Remember, there are only subtle differences (Ports and Auth).

While the steps in the Gallery Item VMRole deployment process will likely remain the same, the actual script could be improved in various ways: Addition of Script Parameters, Separated into Functions, Transformed into a Set of Cmdlets, etc. If anyone takes these improvements on, I will be happy to reference / endorse the published work here in this document.

Finally, as you can see, I have broken the script up into “regions”, each of which builds on the last, to eventually complete all the data collection / command execution for the final Invoke-WebRequest POST to deploy the Gallery Item VMRole. Here is an image illustrating the seven regions:

All that said, if everything goes right during the execution of this example script, you should see something very similar to this:

Use CasesBut wait, WHY would I want to do this?

35 The New World of Tenant Provisioning

Page 39: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Here are some use cases (from both the Service Admin and Tenant Admin personas):

Use Case 1: As a Tenant – Simple avoidance of manual clicking to deploy Gallery Item VMRoles

Use Case 2: As a Tenant – Develop scripts to fully deploy a set of multiple concurrent (and/or dependent) Gallery Item VMRole Deployments (with scripts like this, you have complete control over the “what” and “when”)

Use Case 3: As a Service Provider (or Enterprise acting like one) – Create a custom set of cmdlets encapsulating the parameters and logic into easily consumable/executable commands

Use Case 4: As a Service Provider (or Enterprise acting like one) – Enabling your Tenants/End Users to automate their own Gallery Item VMRole deployments (external to any SMA efforts on the Service Admin side)

And with that, we can do another status check on the scope of the document so far:

Note     In this diagram, we also see that deployment options for both administrator personas have been covered. And we did this with a specific example in mind: the Active Directory Gallery Item VMRole. This was due to the fact that the subsequent example Gallery Item VMRole deployments in this document take a strong dependency on Active Directory. In this way, both the Gallery Item VMRole for Active Directory and the Tenant Network are “table stakes”.

So, at this point, based on this and the previous section of this document, you really have everything necessary to deploy not only the Gallery Item VMRole for Active Directory, but any Gallery Item VMRole you have built (or pulled down off of WebPI (or the Building Clouds Blog)).But hey, I am not going to leave you hanging. The very next section is all about Tenant Workloads, where I will be providing the necessary script updates (to what you have seen so far) to deploy the Gallery Item VMRoles for Lync, SharePoint, and Exchange (for both personas).

36 The New World of Tenant Provisioning

Page 40: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Automated Deployment of Tenant Workloads (Lync, SharePoint, and Exchange)This section of the document is all about describing what it takes and providing the necessary script updates (to what you have seen so far) to deploy the Gallery Item VMRoles for Lync, SharePoint, and Exchange (for both personas).Which means, at least in part, these (previously seen) three diagrams happen to also apply to this section:

37 The New World of Tenant Provisioning

Page 41: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Automated Deployment of Tenant Workloads

(Lync, SharePoint, and Exchange VMRoles; from both Service Admin and Tenant Admin Personas)

Because we established a solid foundation in the previous section of the document, this section really just highlights the script updates necessary to get Automated WAP Deployments to work for OUR PUBLISHED Lync, SharePoint, and Exchange Gallery Item VMRoles. The reason I say “OUR PUBLISHED”, in yelling-case, is to emphasize which Gallery Item VMRoles the example scripts in this section actually directly relate. If you are wondering, “OUR PUBLISHED” Lync, SharePoint, and Exchange Gallery Item VMRoles can be found here: Windows Azure Pack VMRole Gallery Items for Collaboration Workloads

Wait! Wait! Wait! What’s the difference in the script from VMRole to VMRole?

Well, as you saw in the previous sections of the document, no one generic script can be created that handles the deployment from beginning to end. This is due to the fact that each VMRole Definition can vary, based on how that VMRole was created, what fields were included, and which Resource Extensions were added. And while I did my best to keep my scripts generic, there were just portions that had to be hardcoded - dun! dun! dun! The good news is, the hardcoded – dun! dun! dun! stuff is kept to where the scripts differ. Meaning, logic can be introduced to dynamically add the appropriate hardcoded - dun! dun! dun! script portions based on VMRole type.Will I be able to apply what I learn here against the VMRoles I create?

Yes. There will be a “discovery” section in the post which takes you through how to enumerate “What’s different” or “What’s required” as it relates to the Resource Definition (ResDef/ResDefExt), and Resource Definition Configuration (ResDefConfig).What about the Tenant Virtual Network?

This topic will not be discussed again here in this post. Please refer to the “Automated Tenant Virtual Network Deployment” section of this document for more information and example script.Note     The TechNet Gallery Contribution download also includes the example script(s) for automatically creating a Tenant Virtual Network.

The ScopeJust like in the previous two sections, there are various options to choose from when deploying Gallery Item VMRoles. These options are depicted above (the one with all the green checkmarks). To keep this section manageable, I will be providing the example Runbooks / Scripts / Guidance in the following order:Service Administrator in SMA (with the WAP Tenant API Only)

38 The New World of Tenant Provisioning

Page 42: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Existing: SMA Runbook that is the same for each Gallery Item VMRole Deployment

New: Updated SMA Runbooks for the Lync Gallery Item VMRole Deployment

New: Updated SMA Runbooks for the SharePoint Gallery Item VMRole Deployment

New: Updated SMA Runbooks for the Exchange Gallery Item VMRole Deployment

Future Discovery: How to enumerate ResDef/ResDefExt and ResDefConfig Requirements for any Gallery Item VMRole

Tenant Administrator from a PowerShell Script (With the Public WAP Tenant API)

Instead of making a whole big section, reiterating the same thing over and over, I will simply be providing the following:

New: Example Gallery Item VMRole Deployment Script for Active Directory, Lync, Exchange, or SharePoint (as a Tenant Admin against the Public WAP API)

Future Discovery: Modified Example PowerShell script to enumerate ResDef/ResDefExt and ResDefConfig Requirements for any Gallery Item VMRole (as a Tenant Admin against the Public WAP API)

Out of ScopeThere are a couple topics out of scope for this particular section, as they have been covered previously within the document:

1. Automated Tenant Virtual Network Creation 2. Automated Active Directory Gallery Item VMRole Deployment 3. Detailed Review of “The Process” for constructing a Gallery Item

VMRole Deployment Script4. Example VMM PowerShell for Gallery Item VMRole Deployment (“Add-

CloudResource”)5. Pre-Requisites for WAP Tenant API Authentication (“bearer token

authorization”)6. Pre-Requisites for Public WAP Tenant API Authentication (“Windows

Azure PowerShell Module” and “certificates”)

In other words, from a deployment perspective (and from the Tenant’s view), this is our starting point:

39 The New World of Tenant Provisioning

Page 43: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Deployment as a Service Administrator in SMA (with the WAP Tenant API Only)

Existing: SMA Runbook that is the same for each Gallery Item VMRole DeploymentIf we take a look at the “overall structure of the SMA Runbooks” section above, the following SMA Runbook will be the same for each Gallery Item VMRole Deployment (well, depending on your implementation, but definitely for this example) and can be leveraged generically:

For the example script reference here, refer to the “Example PowerShell workflow script for Deploy-VMRole” section above.

New: Updated SMA Runbooks…If we take another look at the “overall structure of my SMA Runbooks” section from Part 2, these two SMA Runbooks will have subtle differences for each Gallery Item VMRole Deployment:

Note     I provide the updated SMA Runbook examples for each Tenant Workload Deployment below.

But before we dive into the SMA Runbook updates, I want to level-set…Because more significant updates take place in the Deploy-TenantVMRole SMA Runbook, this section will concentrate more on it, rather than the Subscription-Create-Dispatcher SMA Runbook.Remember in both previous sections there was a portion of the example PowerShell that created the Gallery Item Parameter Hashtable (for Common Data) and then added to the Gallery Item Parameter Hashtable (for GI Specific Data)?

If not, here is an image to help jog your memory:

40 The New World of Tenant Provisioning

Page 44: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

It is right below this section in the Deploy-TenantVMRole SMA Runbook where we will be adding the updates. Essentially, more logic will be introduced to dynamically add the appropriate hardcoded - dun! dun! dun! script portions based on VMRole type.Note     I will be including the script portions in each respective Tenant Workload sub-section below. Then an all-up Deploy-TenantVMRole SMA Runbook with configuration for all 4 (including Active Directory) Tenant Workload Deployments will be made available after the last sub-section. Also included, will be the all-up Subscription-Create-Dispatcher SMA Runbook with calls for all 4 (including Active Directory) Tenant Workload Deployments.

…for the Lync Gallery Item VMRole Deployment001002003004005

if ($GalleryItemName -eq "Lync"){    $GIParamList += @{RunAsDomainToJoin = $UserID.Split("@")[1]}     $GIParamList += @{LyncServer2013RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}}

…for the SharePoint Gallery Item VMRole Deployment01002003004005006

if ($GalleryItemName -eq "SharePoint"){    $GIParamList += @{RunAsDomainToJoin = $UserID.Split("@")[1]}    $GIParamList += @{SharePointServer2013RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}    $GIParamList += @{SharePointServer2013InstallChoice = "SingleServer"}}

…for the Exchange Gallery Item VMRole Deployment001002003004005006

if ($GalleryItemName -eq "Exchange"){    $GIParamList += @{DomainJoinDomainToJoin = $UserID.Split("@")[1]}    $GIParamList += @{ExchangeServer2013CU2RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}    $GIParamList += @{ExchangeServer2013CU2ExchangeServer2013CU2Organization = "ExchangeOrg"}}

Note     For each of these example script portions, I kept most of the Hashtable Variable building “complex” and/or hardcoded – dun! dun! dun! on purpose. I wanted to avoid creating and leveraging extra variables outside these individual IF blocks. In these examples, much of the string formatting is

41 The New World of Tenant Provisioning

Page 45: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

the same from IF block to IF block, so you can create a “Credential” string before all this, and leverage it throughout.

Options You may want to move some of what I have deemed as “Common Data” to these “GI Specific Data” Hashtables. A good example of this is “VMRoleOSVirtualHardDiskImage = $OSDisk”. Not every VMRole will leverage the same “Common” OS Disk, so to assign different OS Disks to different VMRoles, all you have to do is move the $OSDisk variable assignment to the “GI Specific” Hashtable(s).

Disclaimer     This is a set of examples to handle the GI Specific Data. There are other (and likely better) ways to do this same thing. If you have improvements, please leverage them. If you would like to share those improvements with the community, please let me know, or send a link to your related blog post. I am always happy to cross-post.

Example PowerShell workflow script for Deploy-TenantVMRole

(with IF blocks for DomainController, Lync, SharePoint, and Exchange)

001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054055056057058059

workflow Deploy-TenantVMRole{    param    (        [string]$OwnerUserRole,        [string]$GalleryItemToDeploy,        [string]$VMRoleName,        [string]$VMRoleNamePattern,        [string]$VMRoleSize    )        #Define Variables    $WAPServer = Get-AutomationVariable -Name 'WAP Admin Server'    $Creds = Get-AutomationPSCredential -Name 'PSCredential Name'    $TenantPortalAddress = Get-AutomationVariable -Name 'WAP Tenant Server FQDN'    $SubscriptionID = $OwnerUserRole.Split("_")[1]    $UserID = $OwnerUserRole.Split("_")[0]    $GalleryItemName = $GalleryItemToDeploy.Split(";")[0]    $GIVersion = $GalleryItemToDeploy.Split(";")[1]    $CloudServiceName = "CloudService-4-{0}" -f $SubscriptionID    $OSDisk = Get-AutomationVariable -Name 'Default VMRole OS Disk'    $Password = Get-AutomationVariable -Name 'Password'        # Create Gallery Item Parameter Hashtable (for Common Data)    $GIParamList = @{        VMRoleVMSize = $VMRoleSize        VMRoleOSVirtualHardDiskImage = $OSDisk        VMRoleAdminCredential = "administrator:{0}" -f $Password        VMRoleTimeZone = "Pacific Standard Time"        VMRoleComputerNamePattern = $VMRoleNamePattern        VMRoleNetworkRef = "Tenant Network ({0})" -f $UserID        }

    # Add to Gallery Item Parameter Hashtable (for GI Specific Data)    if ($GalleryItemName -eq "DomainController")    {        $GIParamList += @{DomainControllerWindows2012DomainDNSName = $UserID.Split("@")[1]}         $GIParamList += @{DomainControllerWindows2012DomainNETBIOSName = ($UserID.Split("@")[1]).Split(".")[0]}        $GIParamList += @{DomainControllerWindows2012SafeModeAdminPassword = $Password}    }        if ($GalleryItemName -eq "Lync")    {        $GIParamList += @{RunAsDomainToJoin = $UserID.Split("@")[1]}         $GIParamList += @{LyncServer2013RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}    }        if ($GalleryItemName -eq "SharePoint")    {        $GIParamList += @{RunAsDomainToJoin = $UserID.Split("@")[1]}        $GIParamList += @{SharePointServer2013RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}        $GIParamList += @{SharePointServer2013InstallChoice = "SingleServer"}    }        if ($GalleryItemName -eq "Exchange")    {        $GIParamList += @{DomainJoinDomainToJoin = $UserID.Split("@")[1]}        $GIParamList += @{ExchangeServer2013CU2RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}        $GIParamList += @{ExchangeServer2013CU2ExchangeServer2013CU2Organization = "ExchangeOrg"}

42 The New World of Tenant Provisioning

Page 46: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

060061062063064065066067068069

    }        # Convert Gallery Item Parameter Hash To JSON    $ResDefConfigJSON = ConvertTo-Json $GIParamList        Deploy-VMRole -WAPServer $WAPServer -creds $Creds -TenantPortalAddress $TenantPortalAddress `        -SubscriptionID $SubscriptionID -UserID $UserID -GalleryItemName $GalleryItemName `        -GIVersion $GIVersion -ResDefConfigJSON $ResDefConfigJSON -CloudServiceName $CloudServiceName `        -VMRoleName $VMRoleName}

Note     Obviously I took some liberties with the data sharing in this example. Before I started this SMA Runbook, I knew that each of our Gallery Item VMRoles shared a set of “Common Data” for the Gallery Item Parameter Hashtable. At that point, I just had to figure out which parameters fell into the “GI Specific Data” for each Gallery Item VMRole to be included in the SMA Runbook. Each set of “GI Specific Data” then gets its own IF block, appending to the “Common Data” already in the Gallery Item Parameter Hashtable. More information on “Discovery” of “GI Specific Data” can be found below!

Example PowerShell workflow script for Subscribe-Create-Dispatcher

(with calls for each Tenant Workload)

001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054

workflow Subscription-Create-Dispatcher{    param    (        [object]$resourceObject    )

    if ($resourceObject.AdminID.Length -gt 27) { $AdminId = $AdminId.SubString(0,27) } else { $AdminId = $resourceObject.AdminId }    $OwnerUserRole = $AdminId + "_" + $resourceObject.SubscriptionID    $SubscriptionName = $resourceObject.SubscriptionName        $VMMServer = Get-AutomationVariable -Name 'VMM Server'    $LogicalNetworkName = Get-AutomationVariable -Name 'Default VMM Logical Network'    $PSEmailServer = Get-AutomationVariable -Name 'SMTP Server'    $PSEmailFrom = Get-AutomationVariable -Name 'SMTP From Email'    $PSEmailCC = Get-AutomationVariable -Name 'PSEmailCC'        if ($SubscriptionName -eq "Collaboration Workloads")    {        $CloudName = "Tenant Cloud"                Create-VMNetwork -VmmServerName $VMMServer -OwnerUserRole $OwnerUserRole `            -CloudName $CloudName -LogicalNetworkName $LogicalNetworkName                Send-SMTPNotification -SendNotificationType "Plans" -PSEmailFrom $PSEmailFrom `            -PSEmailTo $AdminId -PSEmailServer $PSEmailServer -PSEmailCC $PSEmailCC `            -WorkloadName $SubscriptionName

        $SubscriptionName + " Plan Selected"                "Deploying Active Directory"        Deploy-TenantVMRole -GalleryItemToDeploy "DomainController;1.0.0.0" `            -OwnerUserRole $OwnerUserRole -VMRoleName "ActiveDirectory" `            -VMRoleNamePattern "DC##" -VMRoleSize "ExtraSmall"                  #No Logic, Just Sleep in this example         Start-Sleep -Seconds 600

        "Deploying Lync"        Deploy-TenantVMRole -GalleryItemToDeploy "Lync;1.0.0.0" `            -OwnerUserRole $OwnerUserRole -VMRoleName "Lync" `            -VMRoleNamePattern "LY##" -VMRoleSize "ExtraLarge"

        "Deploying SharePoint"        Deploy-TenantVMRole -GalleryItemToDeploy "SharePoint;1.0.0.0" `            -OwnerUserRole $OwnerUserRole -VMRoleName "SharePoint" `            -VMRoleNamePattern "SP##" -VMRoleSize "ExtraLarge"

        "Deploying Exchange"        Deploy-TenantVMRole -GalleryItemToDeploy "Exchange;1.0.0.0" `            -OwnerUserRole $OwnerUserRole -VMRoleName "Exchange" `            -VMRoleNamePattern "EX##" -VMRoleSize "ExtraLarge"    }}

43 The New World of Tenant Provisioning

Page 47: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Note     I did not add any “wait logic” in this example. It simply deploys Active Directory, waits 10 minutes and then deploys the other workloads (Lync, SharePoint, and Exchange). For more information on Monitoring and Notifications, refer to this blog post: Automation–Monitoring and Notifying in Windows Azure Pack with SMA.

Future Discovery: How to enumerate ResDef/ResDefExt and ResDefConfig Requirements for any Gallery Item VMRoleSo, how did I know which items in the Gallery Item Parameter Hashtable were “Common” and which were “GI Specific”?Well, other than tearing apart the JSON during my learning process for all this, there is a pretty simple method to extract the necessary data for review.The following is an example PowerShell script which leverages the WAP Tenant API (non-Public), pulls down the specified Gallery Item VMRoles desired for comparison, and outputs a Hashtable containing the Gallery Item VMRole Name and its required Resource Parameters.Example PowerShell script for Get-GIResourceParams

001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050

function Get-GIResourceParams {

    param    (        [object]$Headers,        [string]$TenantPortalAddress,        [string]$SubscriptionID,        [string]$GalleryItemName    )

    # Get Gallery Item Reference    $GIReferenceUri = "https://{0}:30005/{1}/Gallery/GalleryItems/$/MicrosoftCompute.VMRoleGalleryItem?api-version=2013-03" -f $TenantPortalAddress,$SubscriptionID    $GIReferenceData = [xml](Invoke-WebRequest -Uri $GIReferenceUri -Headers $Headers -UseBasicParsing | Select-Object -ExpandProperty Content)    $GalleryItemREF = $GIReferenceData.feed.entry.content.properties.resourcedefinitionUrl | ? {$_ -match $GalleryItemName}

    # Get Gallery Item Resource Definition    $GIResDEFUri = "https://{0}:30005/{1}/{2}/?api-version=2013-03" -f $TenantPortalAddress,$SubscriptionID,$GalleryItemREF    $GIResourceDEFJSON = Invoke-WebRequest -Uri $GIResDEFUri -Headers $Headers -UseBasicParsing | Select-Object -ExpandProperty Content     $ResDef = ConvertFrom-Json $GIResourceDEFJSON

    Return $ResDef.ResourceParameters.Name

}

$WAPServer = "WAP Admin Server Name"$UserID = "User ID (email) of User with Subscription"$TenantPortalAddress = "FQDN of Tenant Portal Address"$SubscriptionID = "Subscription ID for Specified User"$GalleryItems = @("DomainController","Lync","SharePoint","Exchange")

$AdminURI = "https://" + $WAPServer + ":30004"$AuthSite = "https://" + $WAPServer + ":30072"$ClientRealm = "http://azureservices/AdminSite"$token = Get-MgmtSvcToken -Type Windows -AuthenticationSite $AuthSite -ClientRealm $ClientRealm -DisableCertificateValidation

$Headers = @{    Authorization = "Bearer $token"    "x-ms-principal-id" = $UserID }

$GIandResourceParams = @{}

foreach ($GalleryItem in $GalleryItems){    $GIResourceParams = Get-GIResourceParams -Headers $Headers -TenantPortalAddress $TenantPortalAddress `        -SubscriptionID $SubscriptionID -GalleryItemName $GalleryItem

    $GIandResourceParams += @{$GalleryItem = $GIResourceParams}}

$GIandResourceParams

44 The New World of Tenant Provisioning

Page 48: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Note     I leveraged a function within this example script, to minimize duplicate command execution. Modify this example as you see fit. Oh, and it needs to be executed (at least in part) from the WAP Admin Server, or wherever the MgmtSvcAdmin Cmdlets live.

What is the output of this script?

A Hashtable of values you can use to compare/contrast Gallery Item VMRole Resource Parameters:

Challenge     I simply provide the Hashtable worth of data, it is up to you to enumerate the data and make something fancy with Compare-Object command to dynamically compare the Resource Parameters on the fly!

Deployment as a Tenant Administrator from a PowerShell Script (with the Public WAP Tenant API)

New: Deployment Script for Active Directory, Lync, Exchange, or SharePointExample PowerShell script for Active Directory, Lync, Exchange, or SharePoint VMRole Deployment (as a Tenant Admin against the Public WAP API)

001002003004005006007008009010011012013014015016017018019020021

#region GetWAPConnectionData

# Get WAP Subscription Information$WAPSubscription = Get-WAPackSubscription

# Set Subscription$SubscriptionID = $WAPSubscription.SubscriptionId

# Get Management Certificate Info$CertThumb = $WAPSubscription.Certificate.Thumbprint$CertPath = "Cert:\CurrentUser\My\{0}" -f $CertThumb$Cert = Get-Item $CertPath

# Set Tenant Portal Address$TenantPortalAddress = $WAPSubscription.ServiceEndpoint.Host

# Set Port$Port = $WAPSubscription.ServiceEndpoint.Port

#endregion GetWAPConnectionData

#region SetVariables

# Set Gallery Item Name and Version for Match and Deploy$GalleryItemName = "Lync"$GIVersion = "1.0.0.0"

# Set Common Gallery Item Parameters$UserID = "[email protected]"$VMRoleNetwork = "Tenant Network ({0})" -f $UserID$CloudServiceName = "CloudService-4-{0}" -f $SubscriptionID$VMRoleTZ = "Pacific Standard Time"$OSDisk = "Windows Server 2012 Datacenter"$OSDiskVersion = "1.0.0.0"$Password = "Password"

#Set GI Specific Gallery Item Parameters

if ($GalleryItemName -eq "DomainController"){    $VMRoleName = "ActiveDirectory"    $VMRoleNamePattern = "DC##"

45 The New World of Tenant Provisioning

Page 49: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

02202302402502602702802903003103203303403503603703803904004104204304404504604704804905005105205305405505605705805906006106206306406506606706806

    $VMRoleSize = "ExtraSmall"}

if ($GalleryItemName -eq "Lync"){    $VMRoleName = "Lync"    $VMRoleNamePattern = "LY##"    $VMRoleSize = "ExtraLarge"}

if ($GalleryItemName -eq "SharePoint"){    $VMRoleName = "SharePoint"    $VMRoleNamePattern = "SP##"    $VMRoleSize = "ExtraLarge"    $SPInstallChoice = "SingleServer"}

if ($GalleryItemName -eq "Exchange"){    $VMRoleName = "Exchange"    $VMRoleNamePattern = "EX##"    $VMRoleSize = "ExtraLarge"    $ExchangeOrg = "ExchangeOrg"}

#endregion SetVariables

#region GetResDef

# Get Gallery Item Reference$GIReferenceUri = "https://{0}:{1}/{2}/Gallery/GalleryItems/$/MicrosoftCompute.VMRoleGalleryItem?api-version=2013-03" -f $TenantPortalAddress,$Port,$SubscriptionID$GIReferenceData = [xml](Invoke-WebRequest -Certificate $Cert -Uri $GIReferenceUri | Select-Object -ExpandProperty Content)$GalleryItemREF = $GIReferenceData.feed.entry.content.properties.resourcedefinitionUrl | ? {$_ -match $GalleryItemName}

# Get Gallery Item Resource Definition$GIResDEFUri = "https://{0}:{1}/{2}/{3}/?api-version=2013-03" -f $TenantPortalAddress,$Port,$SubscriptionID,$GalleryItemREF$GIResourceDEFJSON = Invoke-WebRequest -Certificate $Cert -Uri $GIResDEFUri | Select-Object -ExpandProperty Content

#Convert ResDef JSON to Dictionary[System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions") | Out-Null$JSSerializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer$ResDef = $JSSerializer.DeserializeObject($GIResourceDEFJSON)

#endregion GetResDef

#region SetResDefConfig

# Create Gallery Item Parameter Hashtable (for Common Data)$GIParamList = @{    VMRoleVMSize = $VMRoleSize    VMRoleOSVirtualHardDiskImage = "{0}:{1}" -f $OSDisk,$OSDiskVersion    VMRoleAdminCredential = "administrator:{0}" -f $Password    VMRoleTimeZone = $VMRoleTZ    VMRoleComputerNamePattern = $VMRoleNamePattern    VMRoleNetworkRef = $VMRoleNetwork    }

# Add to Gallery Item Parameter Hashtable (for GI Specific Data)if ($GalleryItemName -eq "DomainController"){    $GIParamList += @{DomainControllerWindows2012DomainDNSName = $UserID.Split("@")[1]}     $GIParamList += @{DomainControllerWindows2012DomainNETBIOSName = ($UserID.Split("@")[1]).Split(".")[0]}    $GIParamList += @{DomainControllerWindows2012SafeModeAdminPassword = $Password}}    if ($GalleryItemName -eq "Lync"){    $GIParamList += @{RunAsDomainToJoin = $UserID.Split("@")[1]}     $GIParamList += @{LyncServer2013RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}}    if ($GalleryItemName -eq "SharePoint"){    $GIParamList += @{RunAsDomainToJoin = $UserID.Split("@")[1]}    $GIParamList += @{SharePointServer2013RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}    $GIParamList += @{SharePointServer2013InstallChoice = $SPInstallChoice}}    if ($GalleryItemName -eq "Exchange"){    $GIParamList += @{DomainJoinDomainToJoin = $UserID.Split("@")[1]}    $GIParamList += @{ExchangeServer2013CU2RunAsCredential = "{0}\administrator:{1}" -f ($UserID.Split("@")[1]).Split(".")[0],$Password}    $GIParamList += @{ExchangeServer2013CU2ExchangeServer2013CU2Organization = $ExchangeOrg}}    # Convert Gallery Item Parameter Hashtable To JSON$ResDefConfigJSON = ConvertTo-Json $GIParamList

#Add ResDefConfig JSON to Dictionary$ResDefConfig = New-Object 'System.Collections.Generic.Dictionary[String,Object]'$ResDefConfig.Add("Version",$GIVersion)$ResDefConfig.Add("ParameterValues",$ResDefConfigJSON)

#endregion SetResDefConfig

46 The New World of Tenant Provisioning

Page 50: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

9070071072073074075076077078079080081082083084085086087088089090091092093094095096097098099100101102103104105106107108109110111112113114115116

#region GenerateGIPayloadJSON

# Set Gallery Item Payload Variables$GISubstate = $null$GILabel = $VMRoleName$GIName = $VMRoleName$GIProvisioningState = $null$GIInstanceView = $null

# Set Gallery Item Payload Info$GIPayload = @{    "InstanceView" = $GIInstanceView    "Substate" = $GISubstate    "Name" = $GIName    "Label" = $GILabel    "ProvisioningState" = $GIProvisioningState    "ResourceConfiguration" = $ResDefConfig    "ResourceDefinition" = $ResDef    }

# Convert Gallery Item Payload Info To JSON$GIPayloadJSON = ConvertTo-Json $GIPayload -Depth 7

#endregion GenerateGIPayloadJSON

#region GetOrSetCloudService

# Get Cloud Services$CloudServicesUri = "https://{0}:{1}/{2}/CloudServices?api-version=2013-03" -f $TenantPortalAddress,$Port,$SubscriptionID$CloudServicesData = [xml](Invoke-WebRequest -Uri $CloudServicesUri -Certificate $Cert | Select-Object -ExpandProperty Content)$CloudService = $CloudServicesData.feed.entry.content.properties.Name | ? {$_ -match $CloudServiceName}if (!$CloudService) {    # Set Cloud Service Configuration    $CloudServiceConfig = @{        "Name" = $CloudServiceName        "Label" = $CloudServiceName        }

    # Convert Cloud Service Configuration To JSON    $CloudServiceConfigJSON = ConvertTo-Json $CloudServiceConfig

    $CloudServicesData = [xml](Invoke-WebRequest -Uri $CloudServicesUri -Certificate $Cert -Method Post -Body $CloudServiceConfigJSON -ContentType "application/json")    $CloudService = $CloudServicesData.entry.content.properties.Name | ? {$_ -match $CloudServiceName}}

#endregion GetOrSetCloudService

#region DeployGIVMRole

# Set Gallery Item VMRole Deploy URI$GIDeployUri = "https://{0}:{1}/{2}/CloudServices/{3}/Resources/MicrosoftCompute/VMRoles/?api-version=2013-03" -f $TenantPortalAddress,$Port,$SubscriptionID,$CloudService

# Deploy Gallery Item VMRole$VMRoleDeployed = Invoke-WebRequest -Uri $GIDeployUri -Certificate $Cert -Method Post -Body $GIPayloadJSON -ContentType "application/json"$VMRoleDeployed

#endregion DeployGIVMRole

47 The New World of Tenant Provisioning

Page 51: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

11711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316

48 The New World of Tenant Provisioning

Page 52: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

4165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195

Note(s)     Once again, I have several notes about the above script. So I will list them here:

This is an example script. It has been tested against our Demo/Test/Dev environment multiple

times. The following section of the script controls the execution, simply

modify these Variables to Deploy the other available VMRoles included within the script:

The logic is all based on the included IF blocks (two per Gallery Item VMRole).

49 The New World of Tenant Provisioning

Page 53: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

and

It absolutely requires the pre-requisites discussed in Part 3. And while there are alternatives to getting the required variable data based on the Get-WAPackSubscription command, I have found this to be the most efficient/dynamic method.

The $TenantPortalAddress Variable may need to  be set to a specific string, rather than being extracted from the information available from the Get-WAPackSubscription command, specifically if the public portal address is different than the FQDN of WAP Admin Server.

If you are getting errors during deployment like, “Disk with Name (Windows Server 2012 Datacenter) and Version (1.0.0.0) not found while translating Resource Definition for cloud resource.” it is likely that the $OSDisk and/or $OSDiskVersion Variables have incorrect data. The Tenant API does not care so much for the actual OS Disk name, instead, it appears to require the Family Name of the OS Disk.

I chose to leave all the Variable settings within the script. These could very easily be presented as Script Parameters, and fed into the script to make it a bit more generic.

Just like the Service Admin example script, there is a portion of the Resource Definition Configuration (ResDefConfig) that is tied directly to the ResDef/ResDefExt for a given Gallery Item VMRole. When generating the Gallery Item Parameter Hashtable, I have separated the GI specific data from the common GI data. In most cases (especially for the Gallery Item VMRoles produced by my team), the only portion of the script that has to change per VMRole is this GI specific data (and, of course any specific Variable data).

50 The New World of Tenant Provisioning

Page 54: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

This script (for the Tenant Admin) should look nearly identical to the script from Part 2 (for the Service Admin). This is by design, as I wanted to keep as many synergies in play as possible. Remember, there are only subtle differences (Ports and Auth).

While the steps in the Gallery Item VMRole deployment process will likely remain the same, the actual script could be improved in various ways: Addition of Script Parameters, Separated into Functions, Transformed into a Set of Cmdlets, etc. If anyone takes these improvements on, I will be happy to reference / endorse the published work here in this document.

Finally, and once again, the script has been broken up into “regions”, each of which builds on the last, to eventually complete all the data collection / command execution for the final Invoke-WebRequest POST to deploy the Gallery Item VMRole. Here is an image illustrating the seven regions:

After the dust settles on back to back executions, you should see something similar to this in the Tenant Portal:

Future Discovery: Modified Example PowerShell script to enumerate ResDef/ResDefExt and ResDefConfig Requirements for any Gallery Item VMRoleModified Example PowerShell script for Get-GIResourceParams (as a Tenant Admin against the Public WAP API)

001002003004005

function Get-GIResourceParams {

    param    (        [object]$Cert,        [string]$TenantPortalAddress,        [string]$SubscriptionID,        [string]$GalleryItemName    )

51 The New World of Tenant Provisioning

Page 55: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045

    # Get Gallery Item Reference    $GIReferenceUri = "https://{0}:30006/{1}/Gallery/GalleryItems/$/MicrosoftCompute.VMRoleGalleryItem?api-version=2013-03" -f $TenantPortalAddress,$SubscriptionID    $GIReferenceData = [xml](Invoke-WebRequest -Uri $GIReferenceUri -Certificate $Cert -UseBasicParsing | Select-Object -ExpandProperty Content)    $GalleryItemREF = $GIReferenceData.feed.entry.content.properties.resourcedefinitionUrl | ? {$_ -match $GalleryItemName}

    # Get Gallery Item Resource Definition    $GIResDEFUri = "https://{0}:30006/{1}/{2}/?api-version=2013-03" -f $TenantPortalAddress,$SubscriptionID,$GalleryItemREF    $GIResourceDEFJSON = Invoke-WebRequest -Uri $GIResDEFUri -Certificate $Cert -UseBasicParsing | Select-Object -ExpandProperty Content     $ResDef = ConvertFrom-Json $GIResourceDEFJSON

    Return $ResDef.ResourceParameters.Name

}

$WAPSubscription = Get-WAPackSubscription

$CertThumb = $WAPSubscription.Certificate.Thumbprint$CertPath = "Cert:\CurrentUser\My\{0}" -f $CertThumb$Cert = Get-Item $CertPath

$TenantPortalAddress = $WAPSubscription.ServiceEndpoint.Host$SubscriptionID = $WAPSubscription.SubscriptionId$GalleryItems = @("DomainController","Lync","SharePoint","Exchange")

$GIandResourceParams = @{}

foreach ($GalleryItem in $GalleryItems){    $GIResourceParams = Get-GIResourceParams -Cert $Cert -TenantPortalAddress $TenantPortalAddress `        -SubscriptionID $SubscriptionID -GalleryItemName $GalleryItem

    $GIandResourceParams += @{$GalleryItem = $GIResourceParams}}

$GIandResourceParams

Note     This is essentially a copy/paste of the Service Admin script, with modifications to work against the Public WAP Tenant API. The major updates: URL port (changed from 30005 to 30006); and Authorization method (changed from Header with bearer token to Certificate).

And once again, the output of this script is:

52 The New World of Tenant Provisioning

Page 56: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

53 The New World of Tenant Provisioning

Page 57: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Use CasesBut wait, WHY would I want to do this?

Here are some use cases (from both the Service Admin and Tenant Admin personas):

Use Case 1: As a Tenant – Simple avoidance of manual clicking to deploy Gallery Item VMRoles

Use Case 2: As a Tenant – Develop scripts to fully deploy a set of multiple concurrent (and/or dependent) Gallery Item VMRole Deployments (with scripts like this, you have complete control over the “what” and “when”)

Use Case 3: As a Service Provider (or Enterprise acting like one) – Create a custom set of cmdlets encapsulating the parameters and logic into easily consumable/executable commands

Use Case 4: As a Service Provider (or Enterprise acting like one) – Enabling your Tenants/End Users to automate their own Gallery Item VMRole deployments (external to any SMA efforts on the Service Admin side)

54 The New World of Tenant Provisioning

Page 58: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

AppendixThe following are the links referenced throughout this document as well as links related directly to the content:

Links Referenced within the Document Building Clouds Blog: http://aka.ms/BuildingClouds Windows Azure Pack Tenant Provisioning Automation Toolkit TechNet

Gallery Contribution: http://gallery.technet.microsoft.com/Windows-Azure-Pack-Tenant-3e8afd64

VMNetworks Collection API Documentation on MSDN: http://msdn.microsoft.com/en-us/library/dn765986.aspx

Automation–PowerShell Workflow Script Spotlight–Deploying Virtual Machine Manager Service Templates “OnBehalfOf” Tenant Administrator User Roles: http://blogs.technet.com/b/privatecloud/archive/2013/10/24/automation-powershell-workflow-script-spotlight-deploying-virtual-machine-manager-service-templates-onbehalfof-tenant-administrator-user-roles.aspx

Automation–PowerShell Workflow Script Spotlight–Creation and Parameterization of Virtual Machine Manager Run As Accounts for “OnBehalfOf” Service Template Deployment: http://blogs.technet.com/b/privatecloud/archive/2013/10/30/automation-powershell-workflow-script-spotlight-creation-and-parameterization-of-virtual-machine-manager-run-as-accounts-for-onbehalfof-service-template-deployment.aspx

SMART for Runbook Import and Export: http://blogs.technet.com/b/privatecloud/archive/2013/10/23/automation-service-management-automation-sma-runbook-toolkit-spotlight-smart-for-runbook-import-and-export.aspx

Automation–Monitoring and Notifying in Windows Azure Pack with SMA: http://blogs.technet.com/b/privatecloud/archive/2014/01/30/automation-monitoring-and-notifying-in-windows-azure-pack-with-sma.aspx

Bearer Token Bing Search: http://www.bing.com/search?q=bearer+token+authorization&qs=n&form=QBRE&pq=bearer+token+authorization

TechNet Documentation about Get-MgmtSvcToken: http://technet.microsoft.com/en-us/library/dn520915(v=sc.20).aspx

55 The New World of Tenant Provisioning

Page 59: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Using automation with Virtual Machine Clouds: http://technet.microsoft.com/en-us/library/dn457800.aspx

VMRoles Tenant Service Documentation on MSDN: http://msdn.microsoft.com/en-us/library/dn502556.aspx

TechNet Documentation about Add-CloudResource: http://technet.microsoft.com/en-us/library/dn472838(v=sc.20).aspx

Automation–Automating Hybrid Clouds with Windows Azure and PowerShell (Part 2): Public Cloud Environment Provisioning PowerShell Examples: http://blogs.technet.com/b/privatecloud/archive/2013/11/19/automation-automating-hybrid-clouds-with-windows-azure-and-powershell-part-2-public-cloud-environment-provisioning-powershell-examples.aspx

How to install and configure Azure PowerShell: http://www.windowsazure.com/en-us/documentation/articles/install-configure-powershell/

Microsoft Azure CMD Line Tools: http://www.windowsazure.com/en-us/downloads/#cmd-line-tools

Windows Azure Pack VMRole Gallery Items for Collaboration Workloads: http://blogs.technet.com/b/privatecloud/archive/2013/12/11/building-clouds-blog-windows-azure-pack-vmrole-gallery-items.aspx

Links from the Related Blog SeriesAutomation–The New World of Tenant Provisioning with Windows Azure Pack

Part 1: Intro & TOC Part 2: Automated Deployment of Tenant Network and Identity

Workload (Isolated Tenant Virtual Network & Active Directory VMRole; from the Service Admin Persona)

Part 3: Automated Deployment of the Identity Workload as a Tenant Admin (Active Directory VMRole; from the Tenant Admin Persona)

Part 4: Automated Deployment of Tenant Workloads (Lync, SharePoint, and Exchange) (Lync, SharePoint, and Exchange VMRoles; from both Service Admin and Tenant Admin Personas)

Part 5: Working with the SQL Server resource provider, and the ITIL dilemma (by Bruno Saille)

56 The New World of Tenant Provisioning

Page 60: The New World of Tenant Provisioning Web viewThe New World of Tenant Provisioning. ... & Active Directory VMRole. So, ... I realize I keep using this word to emphasize technical significance,

Links to Other Related and Valuable Content Windows Azure Pack–Gallery Item VMRole–References for Creation,

Configuration, and Automation: http://blogs.technet.com/b/privatecloud/archive/2014/03/11/windows-azure-pack-gallery-item-vm-role-resources-for-creation-configuration-and-automation.aspx

8-Minute-Demo: Automated Tenant Provisioning Video: http://www.youtube.com/watch?v=xZIgPAyyg7E

57 The New World of Tenant Provisioning