Merge pull request #255 from Azure/vnext

Merging vnext into master
This commit is contained in:
MatthewMcGlynn 2017-07-10 05:51:55 -07:00 коммит произвёл GitHub
Родитель ad17106460 eb33673f0a
Коммит 3187b271ae
54 изменённых файлов: 9034 добавлений и 5010 удалений

Просмотреть файл

@ -39,11 +39,11 @@ param (
[parameter(HelpMessage="Path for Linux VHD")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
[string] $LinuxImagePath = "https://partner-images.canonical.com/azure/azure_stack/ubuntu-14.04-LTS-microsoft_azure_stack-20161208-9.vhd.zip",
[string] $LinuxImagePath = "http://cloud-images.ubuntu.com/releases/xenial/release/ubuntu-16.04-server-cloudimg-amd64-disk1.vhd.zip",
[parameter(HelpMessage="Linux OS sku")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
[string] $LinuxOSSku = "14.04.3-LTS",
[string] $LinuxOSSku = "16.04-LTS",
[parameter(HelpMessage="Fully qualified domain name of the azure stack environment. Ex: contoso.com")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
@ -61,12 +61,12 @@ param (
[parameter(HelpMessage="Resource group under which all the utilities need to be placed")]
[Parameter(ParameterSetName="default", Mandatory=$false)] [Parameter(ParameterSetName="tenant", Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[string]$CanaryUtilitiesRG = "canur" + [Random]::new().Next(1,999),
[string]$CanaryUtilitiesRG = "cnur" + [Random]::new().Next(1,99),
[parameter(HelpMessage="Resource group under which the virtual machines need to be placed")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[string]$CanaryVMRG = "canvr" + [Random]::new().Next(1,999),
[string]$CanaryVMRG = "cnvr" + [Random]::new().Next(1,99),
[parameter(HelpMessage="Location where all the resource need to deployed and placed")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
@ -86,41 +86,66 @@ param (
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[switch]$NoCleanup,
[parameter(HelpMessage="Specifies whether Canary needs to clean up resources when a failure is encountered")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[switch]$NoCleanupOnFailure,
[parameter(HelpMessage="Specifies the path for log files")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[string]$CanaryLogPath = $env:TMP + "\CanaryLogs$((Get-Date).Ticks)",
[parameter(HelpMessage="Specifies the file name for canary log file")]
[parameter(HelpMessage="Specifies the file name for canary log file")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[string]$CanaryLogFileName = "Canary-Basic-$((Get-Date).Ticks).log"
[string]$CanaryLogFileName = "Canary-Basic-$((Get-Date).Ticks).log",
[parameter(HelpMessage="List of usecases to be excluded from execution")]
[Parameter(ParameterSetName="default", Mandatory=$false)]
[Parameter(ParameterSetName="tenant", Mandatory=$false)]
[string[]]$ExclusionList = ("GetAzureStackInfraRoleInstance"),
[parameter(HelpMessage="Lists the available usecases in Canary")]
[Parameter(ParameterSetName="listavl", Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[switch]$ListAvailable
)
#requires -Modules AzureRM.Profile, AzureRM.AzureStackAdmin
#Requires -RunAsAdministrator
Import-Module -Name $PSScriptRoot\Canary.Utilities.psm1 -Force
Import-Module -Name $PSScriptRoot\..\Connect\AzureStack.Connect.psm1 -Force
Import-Module -Name $PSScriptRoot\..\Infrastructure\AzureStack.Infra.psm1 -Force
Import-Module -Name $PSScriptRoot\..\ComputeAdmin\AzureStack.ComputeAdmin.psm1 -Force
$storageAccName = $CanaryUtilitiesRG + "sa"
$storageCtrName = $CanaryUtilitiesRG + "sc"
$keyvaultName = $CanaryUtilitiesRG + "kv"
$keyvaultCertName = "ASCanaryVMCertificate"
$kvSecretName = $keyvaultName.ToLowerInvariant() + "secret"
$VMAdminUserName = "CanaryAdmin"
$VMAdminUserPass = "CanaryAdmin@123"
$canaryUtilPath = Join-Path -Path $env:TEMP -ChildPath "CanaryUtilities$((Get-Date).Ticks)"
$linuxImagePublisher = "Canonical"
$linuxImageOffer = "UbuntuServer"
$linuxImageVersion = "1.0.0"
Import-Module -Name $PSScriptRoot\Canary.Utilities.psm1 -Force -DisableNameChecking
if (-not $ListAvailable.IsPresent)
{
#requires -Modules AzureRM.Profile, AzureRM.AzureStackAdmin
#Requires -RunAsAdministrator
Import-Module -Name $PSScriptRoot\..\Connect\AzureStack.Connect.psm1 -Force
Import-Module -Name $PSScriptRoot\..\Infrastructure\AzureStack.Infra.psm1 -Force
Import-Module -Name $PSScriptRoot\..\ComputeAdmin\AzureStack.ComputeAdmin.psm1 -Force
}
else
{
$ErrorActionPreference = "SilentlyContinue"
}
$runCount = 1
$tmpLogname = $CanaryLogFileName
while ($runCount -le $NumberOfIterations)
{
if ($NumberOfIterations -gt 1)
{
$CanaryUtilitiesRG = $CanaryUtilitiesRG + $runCount
$CanaryVMRG = $CanaryVMRG + $runCount
}
$storageAccName = $CanaryUtilitiesRG + "sa"
$storageCtrName = $CanaryUtilitiesRG + "sc"
$keyvaultName = $CanaryUtilitiesRG + "kv"
$keyvaultCertName = "ASCanaryVMCertificate"
$kvSecretName = $keyvaultName.ToLowerInvariant() + "secret"
$VMAdminUserName = "CanaryAdmin"
$VMAdminUserPass = "CanaryAdmin@123"
$canaryUtilPath = Join-Path -Path $env:TEMP -ChildPath "CanaryUtilities$((Get-Date).Ticks)"
$linuxImagePublisher = "Canonical"
$linuxImageOffer = "UbuntuServer"
$linuxImageVersion = "1.0.0"
[boolean]$linuxUpload = $false
if (Test-Path -Path $canaryUtilPath)
{
Remove-Item -Path $canaryUtilPath -Force -Recurse
@ -130,15 +155,15 @@ while ($runCount -le $NumberOfIterations)
#
# Start Canary
#
if($ListAvailable){Write-Host "List of scenarios in Canary:" -ForegroundColor Green; $listAvl = $true} else{$listAvl = $false}
$CanaryLogFileName = [IO.Path]::GetFileNameWithoutExtension($tmpLogname) + "-$runCount" + [IO.Path]::GetExtension($tmpLogname)
$CanaryLogFile = Join-Path -Path $CanaryLogPath -ChildPath $CanaryLogFileName
Start-Scenario -Name 'Canary' -Type 'Basic' -LogFilename $CanaryLogFile -ContinueOnFailure $ContinueOnFailure
Start-Scenario -Name 'Canary' -Type 'Basic' -LogFilename $CanaryLogFile -ContinueOnFailure $ContinueOnFailure -ListAvailable $listAvl -ExclusionList $ExclusionList
$SvcAdminEnvironmentName = $EnvironmentName + "-SVCAdmin"
$TntAdminEnvironmentName = $EnvironmentName + "-Tenant"
if(-not $EnvironmentDomainFQDN)
if((-not $EnvironmentDomainFQDN) -and (-not $listAvl))
{
$endptres = Invoke-RestMethod "${AdminArmEndpoint}/metadata/endpoints?api-version=1.0" -ErrorAction Stop
$EnvironmentDomainFQDN = $endptres.portalEndpoint
@ -154,6 +179,7 @@ while ($runCount -le $NumberOfIterations)
-ResourceManagerEndpoint ($asEndpoints.ResourceManagerEndpoint) `
-GalleryEndpoint ($asEndpoints.GalleryEndpoint) `
-GraphEndpoint ($asEndpoints.GraphEndpoint) `
-GraphAudience ($asEndpoints.GraphEndpoint) `
-StorageEndpointSuffix ($asEndpoints.StorageEndpointSuffix) `
-AzureKeyVaultDnsSuffix ($asEndpoints.AzureKeyVaultDnsSuffix) `
-EnableAdfsAuthentication:$asEndpoints.ActiveDirectoryEndpoint.TrimEnd("/").EndsWith("/adfs", [System.StringComparison]::OrdinalIgnoreCase) `
@ -173,54 +199,145 @@ while ($runCount -le $NumberOfIterations)
$defaultSubscription | Select-AzureRmSubscription
}
}
Invoke-Usecase -Name 'ListFabricResourceProviderInfo' -Description "List FabricResourceProvider(FRP) information like storage shares, capacity, logical networks etc." -UsecaseBlock `
{
Invoke-Usecase -Name 'GetAzureStackInfraRole' -Description "List all infrastructure roles" -UsecaseBlock `
{
Get-AzsInfrastructureRole -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackInfraRoleInstance' -Description "List all infrastructure role instances" -UsecaseBlock `
{
Get-AzsInfrastructureRoleInstance -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackLogicalNetwork' -Description "List all logical networks" -UsecaseBlock `
{
Get-AzsLogicalNetwork -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackStorageCapacity' -Description "List storage capacity" -UsecaseBlock `
{
Get-AzSStorageSubsystem -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackStorageShare' -Description "List all storage file shares" -UsecaseBlock `
{
Get-AzsStorageShare -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackScaleUnit' -Description "List Azure Stack scale units in specified Region" -UsecaseBlock `
{
Get-AzsScaleUnit -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackScaleUnitNode' -Description "List nodes in scale unit" -UsecaseBlock `
{
Get-AzsScaleUnitNode -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackIPPool' -Description "List all IP pools" -UsecaseBlock `
{
Get-AzsIpPool -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackMacPool' -Description "List all MAC address pools " -UsecaseBlock `
{
Get-AzsMacPool -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackGatewayPool' -Description "List all gateway pools" -UsecaseBlock `
{
Get-AzsGatewayPool -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackSLBMux' -Description "List all SLB MUX instances" -UsecaseBlock `
{
Get-AzsSlbMux -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackGateway' -Description "List all gateway" -UsecaseBlock `
{
Get-AzsGateway -Location $ResourceLocation
}
}
Invoke-Usecase -Name 'ListHealthResourceProviderAlerts' -Description "List all HealthResourceProvider(HRP) alerts " -UsecaseBlock `
{
Invoke-Usecase -Name 'GetAzureStackAlert' -Description "List all alerts" -UsecaseBlock `
{
Get-AzsAlert -Location $ResourceLocation
}
}
Invoke-Usecase -Name 'ListUpdatesResourceProviderInfo' -Description "List URP information like summary of updates available, update to be applied, last update applied etc." -UsecaseBlock `
{
Invoke-Usecase -Name 'GetAzureStackUpdateSummary' -Description "List summary of updates status" -UsecaseBlock `
{
Get-AzSUpdateLocation -Location $ResourceLocation
}
Invoke-Usecase -Name 'GetAzureStackUpdateToApply' -Description "List all updates that can be applied" -UsecaseBlock `
{
Get-AzsUpdate -Location $ResourceLocation
}
}
if ($WindowsISOPath)
{
Invoke-Usecase -Name 'UploadWindows2016ImageToPIR' -Description "Uploads a windows server 2016 image to the PIR" -UsecaseBlock `
{
if (-not (Get-AzureRmVMImage -Location $ResourceLocation -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Sku "2016-Datacenter-Core" -ErrorAction SilentlyContinue))
{
New-Server2016VMImage -ISOPath $WindowsISOPath -TenantId $TenantID -EnvironmentName $SvcAdminEnvironmentName -Location $ResourceLocation -Version Core -AzureStackCredentials $ServiceAdminCredentials -CreateGalleryItem $false
New-AzsServer2016VMImage -ISOPath $WindowsISOPath -Location $ResourceLocation -Version Core -CreateGalleryItem $false
}
}
}
if ((Get-Volume ((Get-Item -Path $ENV:TMP).PSDrive.Name)).SizeRemaining/1GB -gt 35)
{
Invoke-Usecase -Name 'UploadLinuxImageToPIR' -Description "Uploads Linux image to the PIR" -UsecaseBlock `
[boolean]$invalidUri = $false
try {Invoke-WebRequest -Uri $LinuxImagePath -UseBasicParsing -DisableKeepAlive -Method Head -ErrorAction SilentlyContinue | Out-Null}
catch {$invalidUri = $true}
if (-not $invalidUri)
{
try
Invoke-Usecase -Name 'UploadLinuxImageToPIR' -Description "Uploads Linux image to the PIR" -UsecaseBlock `
{
if (-not (Get-AzureRmVMImage -Location $ResourceLocation -PublisherName $linuxImagePublisher -Offer $linuxImageOffer -Sku $LinuxOSSku -ErrorAction SilentlyContinue))
try
{
$CanaryCustomImageFolder = Join-Path -Path $env:TMP -childPath "CanaryCustomImage$((Get-Date).Ticks)"
if (Test-Path -Path $CanaryCustomImageFolder)
if (-not (Get-AzureRmVMImage -Location $ResourceLocation -PublisherName $linuxImagePublisher -Offer $linuxImageOffer -Sku $LinuxOSSku -ErrorAction SilentlyContinue))
{
Remove-Item -Path $CanaryCustomImageFolder -Force -Recurse
}
New-Item -Path $CanaryCustomImageFolder -ItemType Directory
$CustomVHDPath = CopyImage -ImagePath $LinuxImagePath -OutputFolder $CanaryCustomImageFolder
Add-VMImage -publisher $linuxImagePublisher -offer $linuxImageOffer -sku $LinuxOSSku -version $linuxImageVersion -osDiskLocalPath $CustomVHDPath -osType Linux -tenantID $TenantID -azureStackCredentials $ServiceAdminCredentials -Location $ResourceLocation -CreateGalleryItem $false -EnvironmentName $SvcAdminEnvironmentName
Remove-Item $CanaryCustomImageFolder -Force -Recurse
}
}
catch
{
Remove-Item -Path $CanaryCustomImageFolder -Force -Recurse
throw [System.Exception]"Failed to upload the linux image to PIR. `n$($_.Exception.Message)"
$CanaryCustomImageFolder = Join-Path -Path $env:TMP -childPath "CanaryCustomImage$((Get-Date).Ticks)"
if (Test-Path -Path $CanaryCustomImageFolder)
{
Remove-Item -Path $CanaryCustomImageFolder -Force -Recurse
}
New-Item -Path $CanaryCustomImageFolder -ItemType Directory
$CustomVHDPath = CopyImage -ImagePath $LinuxImagePath -OutputFolder $CanaryCustomImageFolder
Add-AzsVMImage -publisher $linuxImagePublisher -offer $linuxImageOffer -sku $LinuxOSSku -version $linuxImageVersion -osDiskLocalPath $CustomVHDPath -osType Linux -Location $ResourceLocation -CreateGalleryItem $false
Remove-Item $CanaryCustomImageFolder -Force -Recurse
$linuxUpload = $true
}
}
catch
{
Remove-Item -Path $CanaryCustomImageFolder -Force -Recurse
throw [System.Exception]"Failed to upload the linux image to PIR. `n$($_.Exception.Message)"
}
}
}
}
if ($TenantAdminCredentials)
if (($TenantAdminCredentials) -or ($ListAvailable))
{
$subscriptionRGName = "ascansubscrrg" + [Random]::new().Next(1,999)
$tenantPlanName = "ascantenantplan" + [Random]::new().Next(1,999)
$tenantOfferName = "ascantenantoffer" + [Random]::new().Next(1,999)
$tenantSubscriptionName = "ascanarytenantsubscription" + [Random]::new().Next(1,999)
$canaryDefaultTenantSubscription = "canarytenantdefaultsubscription" + [Random]::new().Next(1,999)
$subscriptionRGName = $CanaryUtilitiesRG + "subscrrg" + [Random]::new().Next(1,999)
$tenantPlanName = $CanaryUtilitiesRG + "tenantplan" + [Random]::new().Next(1,999)
$tenantOfferName = $CanaryUtilitiesRG + "tenantoffer" + [Random]::new().Next(1,999)
$tenantSubscriptionName = $CanaryUtilitiesRG + "tenantsubscription" + [Random]::new().Next(1,999)
$canaryDefaultTenantSubscription = $CanaryUtilitiesRG + "tenantdefaultsubscription" + [Random]::new().Next(1,999)
if (-not $TenantArmEndpoint)
if ((-not $TenantArmEndpoint) -and (-not $ListAvailable.IsPresent))
{
throw [System.Exception] "Tenant ARM endpoint is required."
}
@ -234,11 +351,13 @@ while ($runCount -le $NumberOfIterations)
-ResourceManagerEndpoint ($asEndpoints.ResourceManagerEndpoint) `
-GalleryEndpoint ($asEndpoints.GalleryEndpoint) `
-GraphEndpoint ($asEndpoints.GraphEndpoint) `
-GraphAudience ($asEndpoints.GraphEndpoint) `
-StorageEndpointSuffix ($asEndpoints.StorageEndpointSuffix) `
-AzureKeyVaultDnsSuffix ($asEndpoints.AzureKeyVaultDnsSuffix) `
-EnableAdfsAuthentication:$asEndpoints.ActiveDirectoryEndpoint.TrimEnd("/").EndsWith("/adfs", [System.StringComparison]::OrdinalIgnoreCase) `
-ErrorAction Stop
}
Invoke-Usecase -Name 'CreateResourceGroupForTenantSubscription' -Description "Create a resource group $subscriptionRGName for the tenant subscription" -UsecaseBlock `
{
if (Get-AzureRmResourceGroup -Name $subscriptionRGName -ErrorAction SilentlyContinue)
@ -290,6 +409,162 @@ while ($runCount -le $NumberOfIterations)
}
}
Invoke-Usecase -Name 'RoleAssignmentAndCustomRoleDefinition' -Description "Assign a reader role and create a custom role definition" -UsecaseBlock `
{
if (-not $ListAvailable.IsPresent)
{
$servicePrincipal = (Get-AzureRmADServicePrincipal)[0]
$customRoleName = "CustomCanaryRole-" + [Random]::new().Next(1,99)
}
Invoke-Usecase -Name 'ListAssignedRoles' -Description "List assigned roles to Service Principle - $($servicePrincipal.DisplayName)" -UsecaseBlock `
{
Get-AzureRmRoleAssignment -ObjectId $servicePrincipal.Id -ErrorAction Stop
}
Invoke-Usecase -Name 'ListExistingRoleDefinitions' -Description "List existing Role Definitions" -UsecaseBlock `
{
$availableRoles = Get-AzureRmRoleDefinition -ErrorAction Stop
if (-not $availableRoles)
{
throw [System.Exception] "No roles are available."
}
else
{
$availableRoles
$availableRolesNames = $availableRoles.Name
$mustHaveRoles = @("Owner", "Reader", "Contributor")
$match = Compare-Object $mustHaveRoles $availableRolesNames
if ($match -and ($match | Where-Object {$_.SideIndicator -eq "<="}))
{
$notAvailableRoles = ($match | Where-Object {$_.SideIndicator -eq "<="}).InputObject
throw [System.Exception] "Some must have Role Definitions are not available. Number of missing Role Definitions - $($notAvailableRoles.Count). Missing Role Definitions - $notAvailableRoles"
}
}
}
Invoke-Usecase -Name 'GetProviderOperations' -Description "Get provider operations for all resource providers" -UsecaseBlock `
{
$resourceProviders = Get-AzureRmResourceProvider -ListAvailable
# Some of the RPs have not implemented their operations API yet. So update this exclusion list whenever any RP implements its operations API
$rpOperationsExclusionList = @("Microsoft.Commerce", "Microsoft.Gallery", "Microsoft.Insights")
$totalOperationsPerRP = @()
foreach($rp in $resourceProviders)
{
$operations = Get-AzureRMProviderOperation "$($rp.ProviderNamespace)/*" -ErrorAction Stop
$operationObj = New-Object -TypeName System.Object
$operationObj | Add-Member -Type NoteProperty -Name ResourceProvider -Value $rp.ProviderNamespace
if (-not $operations)
{
$operationObj | Add-Member -Type NoteProperty -Name TotalProviderOperations -Value 0
}
else
{
$operationObj | Add-Member -Type NoteProperty -Name TotalProviderOperations -Value $operations.Count
}
$totalOperationsPerRP += $operationObj
}
$totalOperationsPerRP
if ($totalOperationsPerRP -and ($totalOperationsPerRP | Where-Object {$_.TotalProviderOperations -eq 0}))
{
$rpWithNoOperations = ($totalOperationsPerRP | Where-Object {$_.TotalProviderOperations -eq 0}).ResourceProvider
$match = Compare-Object $rpOperationsExclusionList $rpWithNoOperations
if ($match -and ($match | Where-Object {$_.SideIndicator -eq "=>"}))
{
$missed = ($match | Where-Object {$_.SideIndicator -eq "=>"}).InputObject
throw [System.Exception] "Some Resource Providers have zero Provider Operations. Number of Resource Providers with zero Provider Operations - $($missed.Count). Resource Providers with zero Provider Operations - $missed"
}
}
}
Invoke-Usecase -Name 'AssignReaderRole' -Description "Assign Reader role to Service Principle - $($servicePrincipal.DisplayName)" -UsecaseBlock `
{
$readerRole = Get-AzureRmRoleDefinition -Name Reader
$subscriptionID = (Get-AzureRmSubscription -SubscriptionName $tenantSubscriptionName).SubscriptionId
$allAssignedRoles = Get-AzureRmRoleAssignment -ObjectId $servicePrincipal.Id -ErrorAction Stop
if ($subscriptionID -and $readerRole -and (-not $allAssignedRoles -or ($allAssignedRoles -and -not ($allAssignedRoles | Where-Object {$_.RoleDefinitionName -eq $readerRole.Name}))))
{
New-AzureRmRoleAssignment -Scope "/Subscriptions/$subscriptionID" -RoleDefinitionName $readerRole.Name -ObjectId $servicePrincipal.Id -ErrorAction Stop
}
}
Invoke-Usecase -Name 'VerifyReaderRoleAssignment' -Description "Verify if the Service Principle has got Reader role assigned successfully" -UsecaseBlock `
{
$readerRole = Get-AzureRmRoleDefinition -Name Reader
$subscriptionID = (Get-AzureRmSubscription -SubscriptionName $tenantSubscriptionName).SubscriptionId
if ($subscriptionID -and $readerRole -and (-not (Get-AzureRmRoleAssignment -RoleDefinitionName $readerRole.Name -Scope "/Subscriptions/$subscriptionID" -ErrorAction Stop)))
{
throw [System.Exception] "Unable to assign role ($readerRole.Name) to Service Principle ($servicePrincipal.Id) for subscription $tenantSubscriptionName"
}
}
Invoke-Usecase -Name 'RemoveReaderRoleAssignment' -Description "Remove Reader role assignment from Service Principle - $($servicePrincipal.DisplayName)" -UsecaseBlock `
{
$readerRole = Get-AzureRmRoleDefinition -Name Reader
$subscriptionID = (Get-AzureRmSubscription -SubscriptionName $tenantSubscriptionName).SubscriptionId
if ($subscriptionID -and $readerRole -and (Get-AzureRmRoleAssignment -RoleDefinitionName $readerRole.Name -Scope "/Subscriptions/$subscriptionID" -ErrorAction Stop))
{
Remove-AzureRmRoleAssignment -Scope "/Subscriptions/$subscriptionID" -RoleDefinitionName $readerRole.Name -ObjectId $servicePrincipal.Id -Force -ErrorAction Stop
}
}
Invoke-Usecase -Name 'CustomRoleDefinition' -Description "Create a custom Role Definition - $customRoleName" -UsecaseBlock `
{
$subscriptionID = (Get-AzureRmSubscription -SubscriptionName $tenantSubscriptionName).SubscriptionId
if (Get-AzureRmRoleDefinition -Name $customRoleName)
{
Remove-AzureRmRoleDefinition -Name $customRoleName -Scope "/Subscriptions/$subscriptionID" -Force -ErrorAction Stop
}
$role = Get-AzureRmRoleDefinition -Name Reader
$role.Id = $null
$role.Name = $customRoleName
$role.Description = "Custom role definition for Canary"
$role.Actions.Clear()
$role.Actions.Add("Microsoft.Authorization/*/Read")
$role.AssignableScopes.Clear()
$role.AssignableScopes.Add("/Subscriptions/$subscriptionID")
New-AzureRmRoleDefinition -Role $role -ErrorAction Stop
if (-not (Get-AzureRmRoleDefinition -Name $customRoleName -Scope "/Subscriptions/$subscriptionID" -ErrorAction Stop))
{
throw [System.Exception] "Unable to create custom role definition ($customRoleName) for subscription $tenantSubscriptionName"
}
}
Invoke-Usecase -Name 'ListRoleDefinitionsAfterCustomRoleCreation' -Description "List existing Role Definitions" -UsecaseBlock `
{
$availableRoles = Get-AzureRmRoleDefinition -ErrorAction Stop
if (-not $availableRoles)
{
throw [System.Exception] "No roles are available."
}
else
{
$availableRoles
$availableRolesNames = $availableRoles.Name
$mustHaveRoles = @("Owner", "Reader", "Contributor")
$match = Compare-Object $mustHaveRoles $availableRolesNames
if ($match -and ($match | Where-Object {$_.SideIndicator -eq "<="}))
{
$notAvailableRoles = ($match | Where-Object {$_.SideIndicator -eq "<="}).InputObject
throw [System.Exception] "Some must have Role Definitions are not available. Number of missing Role Definitions - $($notAvailableRoles.Count). Missing Role Definitions - $notAvailableRoles"
}
}
}
Invoke-Usecase -Name 'RemoveCustomRoleDefinition' -Description "Remove custom role definition - $customRoleName" -UsecaseBlock `
{
$subscriptionID = (Get-AzureRmSubscription -SubscriptionName $tenantSubscriptionName).SubscriptionId
if(Get-AzureRmRoleDefinition -Name $customRoleName -Scope "/Subscriptions/$subscriptionID" -ErrorAction Stop)
{
Remove-AzureRmRoleDefinition -Name $customRoleName -Scope "/Subscriptions/$subscriptionID" -Force -ErrorAction Stop
}
else
{
throw [System.Exception] "Custom role definition ($customRoleName) for subscription $tenantSubscriptionName is not available"
}
}
}
Invoke-Usecase -Name 'RegisterResourceProviders' -Description "Register resource providers" -UsecaseBlock `
{
Get-AzureRmResourceProvider -ListAvailable | Register-AzureRmResourceProvider -Force
@ -440,40 +715,69 @@ while ($runCount -le $NumberOfIterations)
New-AzureRmResourceGroup -Name $CanaryVMRG -Location $ResourceLocation -ErrorAction Stop
}
$pirQueryRes = Invoke-Usecase -Name 'QueryImagesFromPIR' -Description "Queries the images in Platform Image Repository to retrieve the OS Version to deploy on the VMs" -UsecaseBlock `
{
$osVersion = ""
[boolean]$linuxImgExists = $false
$sw = [system.diagnostics.stopwatch]::startNew()
while (([string]::IsNullOrEmpty($osVersion)) -and ($sw.ElapsedMilliseconds -lt 300000))
{
# Returns all the images that are available in the PIR
$pirImages = Get-AzureRmVMImagePublisher -Location $ResourceLocation | Get-AzureRmVMImageOffer | Get-AzureRmVMImageSku | Get-AzureRMVMImage | Get-AzureRmVMImage
foreach($image in $pirImages)
{
# Canary specific check to see if the required Ubuntu image was successfully uploaded and available in PIR
if ($image.PublisherName.Equals("Canonical") -and $image.Offer.Equals("UbuntuServer") -and $image.Skus.Equals($LinuxOSSku))
{
$linuxImgExists = $true
}
if ($image.PublisherName.Equals("MicrosoftWindowsServer") -and $image.Offer.Equals("WindowsServer") -and $image.Skus.Equals("2016-Datacenter-Core"))
{
$osVersion = "2016-Datacenter-Core"
}
elseif ($image.PublisherName.Equals("MicrosoftWindowsServer") -and $image.Offer.Equals("WindowsServer") -and $image.Skus.Equals("2016-Datacenter"))
{
$osVersion = "2016-Datacenter"
}
elseif ($image.PublisherName.Equals("MicrosoftWindowsServer") -and $image.Offer.Equals("WindowsServer") -and $image.Skus.Equals("2012-R2-Datacenter"))
{
$osVersion = "2012-R2-Datacenter"
}
}
Start-Sleep -Seconds 20
}
$sw.Stop()
if (($linuxUpload) -and (-not $linuxImgExists))
{
throw [System.Exception] "Unable to find Ubuntu image (Ubuntu $LinuxOSSku) in PIR or failed to retrieve the image from PIR"
}
if ([string]::IsNullOrEmpty($osVersion))
{
throw [System.Exception] "Unable to find windows image in PIR or failed to retrieve the image from PIR"
}
$osVersion, $linuxImgExists
}
[string]$osVersion = $pirQueryRes[2]
[boolean]$linuxImgExists = $pirQueryRes[3]
Invoke-Usecase -Name 'DeployARMTemplate' -Description "Deploy ARM template to setup the virtual machines" -UsecaseBlock `
{
$kvSecretId = (Get-AzureKeyVaultSecret -VaultName $keyVaultName -Name $kvSecretName -IncludeVersions -ErrorAction Stop).Id
$osVersion = ""
if (Get-AzureRmVMImage -Location $ResourceLocation -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Sku "2016-Datacenter-Core" -ErrorAction SilentlyContinue)
{
$osVersion = "2016-Datacenter-Core"
}
elseif (Get-AzureRmVMImage -Location $ResourceLocation -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Sku "2016-Datacenter" -ErrorAction SilentlyContinue)
{
$osVersion = "2016-Datacenter"
}
elseif (Get-AzureRmVMImage -Location $ResourceLocation -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Sku "2012-R2-Datacenter" -ErrorAction SilentlyContinue)
{
$osVersion = "2012-R2-Datacenter"
}
$linuxImgExists = $false
if (Get-AzureRmVMImage -Location $ResourceLocation -PublisherName "Canonical" -Offer "UbuntuServer" -Sku $LinuxOSSku -ErrorAction SilentlyContinue)
{
$linuxImgExists = $true
}
$templateDeploymentName = "CanaryVMDeployment"
$parameters = @{"VMAdminUserName" = $VMAdminUserName;
"VMAdminUserPassword" = $VMAdminUserPass;
"ASCanaryUtilRG" = $CanaryUtilitiesRG;
"ASCanaryUtilSA" = $storageAccName;
"ASCanaryUtilSC" = $storageCtrName;
"vaultName" = $keyvaultName;
"windowsOSVersion" = $osVersion;
"secretUrlWithVersion" = $kvSecretId;
"LinuxImagePublisher" = $linuxImagePublisher;
"LinuxImageOffer" = $linuxImageOffer;
"LinuxImageSku" = $LinuxOSSku}
$parameters = @{"VMAdminUserName" = $VMAdminUserName;
"VMAdminUserPassword" = $VMAdminUserPass;
"ASCanaryUtilRG" = $CanaryUtilitiesRG;
"ASCanaryUtilSA" = $storageAccName;
"ASCanaryUtilSC" = $storageCtrName;
"vaultName" = $keyvaultName;
"windowsOSVersion" = $osVersion;
"secretUrlWithVersion" = $kvSecretId;
"LinuxImagePublisher" = $linuxImagePublisher;
"LinuxImageOffer" = $linuxImageOffer;
"LinuxImageSku" = $LinuxOSSku;
"storageAccountEndPoint" = "https://$EnvironmentDomainFQDN/"}
if (-not $linuxImgExists)
{
$templateError = Test-AzureRmResourceGroupDeployment -ResourceGroupName $CanaryVMRG -TemplateFile $PSScriptRoot\azuredeploy.json -TemplateParameterObject $parameters
@ -496,6 +800,12 @@ while ($runCount -le $NumberOfIterations)
}
}
Invoke-Usecase -Name 'RetrieveResourceDeploymentTimes' -Description "Retrieves the resources deployment times from the ARM template deployment" -UsecaseBlock `
{
$templateDeploymentName = "CanaryVMDeployment"
(Get-AzureRmResourceGroupDeploymentOperation -Deploymentname $templateDeploymentName -ResourceGroupName $CanaryVMRG).Properties | Select-Object ProvisioningOperation,Duration,ProvisioningState,StatusCode,TargetResource | Format-Table -AutoSize
}
$canaryWindowsVMList = @()
$canaryWindowsVMList = Invoke-Usecase -Name 'QueryTheVMsDeployed' -Description "Queries for the VMs that were deployed using the ARM template" -UsecaseBlock `
{
@ -559,18 +869,24 @@ while ($runCount -le $NumberOfIterations)
if (($pubVMObject = Get-AzureRmVM -ResourceGroupName $CanaryVMRG -Name $publicVMName -ErrorAction Stop) -and ($pvtVMObject = Get-AzureRmVM -ResourceGroupName $CanaryVMRG -Name $privateVMName -ErrorAction Stop))
{
Set-item wsman:\localhost\Client\TrustedHosts -Value $publicVMIP -Force -Confirm:$false
if ($publicVMSession = New-PSSession -ComputerName $publicVMIP -Credential $vmCreds -ErrorAction Stop)
$sw = [system.diagnostics.stopwatch]::startNew()
while (-not($publicVMSession = New-PSSession -ComputerName $publicVMIP -Credential $vmCreds -ErrorAction SilentlyContinue)){if (($sw.ElapsedMilliseconds -gt 240000) -and (-not($publicVMSession))){$sw.Stop(); throw [System.Exception]"Unable to establish a remote session to the tenant VM using public IP: $publicVMIP"}; Start-Sleep -Seconds 15}
if ($publicVMSession)
{
Invoke-Command -Session $publicVMSession -Script{param ($privateIP) Set-item wsman:\localhost\Client\TrustedHosts -Value $privateIP -Force -Confirm:$false} -ArgumentList $privateVMIP | Out-Null
$privateVMResponseFromRemoteSession = Invoke-Command -Session $publicVMSession -Script{param ($privateIP, $vmCreds, $scriptToRun) $privateSess = New-PSSession -ComputerName $privateIP -Credential $vmCreds; Invoke-Command -Session $privateSess -Script{param($script) Invoke-Expression $script} -ArgumentList $scriptToRun} -ArgumentList $privateVMIP, $vmCreds, $vmCommsScriptBlock
$privateVMResponseFromRemoteSession = Invoke-Command -Session $publicVMSession -Script{param ($privateIP, $vmCreds, $scriptToRun) $sw = [system.diagnostics.stopwatch]::startNew(); while (-not($privateSess = New-PSSession -ComputerName $privateIP -Credential $vmCreds -ErrorAction SilentlyContinue)){if (($sw.ElapsedMilliseconds -gt 240000) -and (-not($privateSess))){$sw.Stop(); throw [System.Exception]"Unable to establish a remote session to the tenant VM using private IP: $privateIP"}; Start-Sleep -Seconds 15}; Invoke-Command -Session $privateSess -Script{param($script) Invoke-Expression $script} -ArgumentList $scriptToRun} -ArgumentList $privateVMIP, $vmCreds, $vmCommsScriptBlock -ErrorVariable remoteExecError 2>$null
$publicVMSession | Remove-PSSession -Confirm:$false
if ($remoteExecError)
{
throw [System.Exception]"$remoteExecError"
}
if ($privateVMResponseFromRemoteSession)
{
$publicVMSession | Remove-PSSession -Confirm:$false
$privateVMResponseFromRemoteSession
}
else
{
throw [System.Exception]"Public VM was not able to talk to the Private VM via the private IP"
throw [System.Exception]"The expected certificate from KV was not found on the tenant VM with private IP: $privateVMIP"
}
}
}
@ -707,18 +1023,24 @@ while ($runCount -le $NumberOfIterations)
if (($pubVMObject = Get-AzureRmVM -ResourceGroupName $CanaryVMRG -Name $publicVMName -ErrorAction Stop) -and ($pvtVMObject = Get-AzureRmVM -ResourceGroupName $CanaryVMRG -Name $privateVMName -ErrorAction Stop))
{
Set-item wsman:\localhost\Client\TrustedHosts -Value $publicVMIP -Force -Confirm:$false
if ($publicVMSession = New-PSSession -ComputerName $publicVMIP -Credential $vmCreds -ErrorAction Stop)
$sw = [system.diagnostics.stopwatch]::startNew()
while (-not($publicVMSession = New-PSSession -ComputerName $publicVMIP -Credential $vmCreds -ErrorAction SilentlyContinue)){if (($sw.ElapsedMilliseconds -gt 240000) -and (-not($publicVMSession))){$sw.Stop(); throw [System.Exception]"Unable to establish a remote session to the tenant VM using public IP: $publicVMIP"}; Start-Sleep -Seconds 15}
if ($publicVMSession)
{
Invoke-Command -Session $publicVMSession -Script{param ($privateIP) Set-item wsman:\localhost\Client\TrustedHosts -Value $privateIP -Force -Confirm:$false} -ArgumentList $privateVMIP | Out-Null
$privateVMResponseFromRemoteSession = Invoke-Command -Session $publicVMSession -Script{param ($privateIP, $vmCreds, $scriptToRun) $privateSess = New-PSSession -ComputerName $privateIP -Credential $vmCreds; Invoke-Command -Session $privateSess -Script{param($script) Invoke-Expression $script} -ArgumentList $scriptToRun} -ArgumentList $privateVMIP, $vmCreds, $vmCommsScriptBlock
$privateVMResponseFromRemoteSession = Invoke-Command -Session $publicVMSession -Script{param ($privateIP, $vmCreds, $scriptToRun) $sw = [system.diagnostics.stopwatch]::startNew(); while (-not($privateSess = New-PSSession -ComputerName $privateIP -Credential $vmCreds -ErrorAction SilentlyContinue)){if (($sw.ElapsedMilliseconds -gt 240000) -and (-not($privateSess))){$sw.Stop(); throw [System.Exception]"Unable to establish a remote session to the tenant VM using private IP: $privateIP"}; Start-Sleep -Seconds 15}; Invoke-Command -Session $privateSess -Script{param($script) Invoke-Expression $script} -ArgumentList $scriptToRun} -ArgumentList $privateVMIP, $vmCreds, $vmCommsScriptBlock -ErrorVariable remoteExecError 2>$null
$publicVMSession | Remove-PSSession -Confirm:$false
if ($remoteExecError)
{
throw [System.Exception]"$remoteExecError"
}
if ($privateVMResponseFromRemoteSession)
{
$publicVMSession | Remove-PSSession -Confirm:$false
$privateVMResponseFromRemoteSession
}
else
{
throw [System.Exception]"Public VM was not able to talk to the Private VM via the private IP"
throw [System.Exception]"Host name could not be retrieved from the tenant VM with private IP: $privateVMIP"
}
}
}
@ -743,69 +1065,82 @@ while ($runCount -le $NumberOfIterations)
if (-not $NoCleanup)
{
Invoke-Usecase -Name 'DeleteVMWithPrivateIP' -Description "Delete the VM with private IP" -UsecaseBlock `
if (-not ($NoCleanupOnFailure -and (Get-CanaryFailureStatus)))
{
if ($vmObject = Get-AzureRmVM -ResourceGroupName $CanaryVMRG -Name $privateVMName -ErrorAction Stop)
Invoke-Usecase -Name 'DeleteVMWithPrivateIP' -Description "Delete the VM with private IP" -UsecaseBlock `
{
$deleteVM = $vmObject | Remove-AzureRmVM -Force -ErrorAction Stop
if (-not (($deleteVM.StatusCode -eq "OK") -and ($deleteVM.IsSuccessStatusCode)))
if ($vmObject = Get-AzureRmVM -ResourceGroupName $CanaryVMRG -Name $privateVMName -ErrorAction Stop)
{
throw [System.Exception]"Failed to delete the VM $privateVMName"
}
}
}
Invoke-Usecase -Name 'DeleteVMResourceGroup' -Description "Delete the resource group that contains all the VMs and corresponding resources" -UsecaseBlock `
{
if ($removeRG = Get-AzureRmResourceGroup -Name $CanaryVMRG -ErrorAction Stop)
{
$removeRG | Remove-AzureRmResourceGroup -Force -ErrorAction Stop
}
}
Invoke-Usecase -Name 'DeleteUtilitiesResourceGroup' -Description "Delete the resource group that contains all the utilities and corresponding resources" -UsecaseBlock `
{
if ($removeRG = Get-AzureRmResourceGroup -Name $CanaryUtilitiesRG -ErrorAction Stop)
{
$removeRG | Remove-AzureRmResourceGroup -Force -ErrorAction Stop
}
}
if ($TenantAdminCredentials)
{
Invoke-Usecase -Name 'TenantRelatedcleanup' -Description "Remove all the tenant related stuff" -UsecaseBlock `
{
Invoke-Usecase -Name 'DeleteTenantSubscriptions' -Description "Remove all the tenant related subscriptions" -UsecaseBlock `
{
if ($subs = Get-AzureRmTenantSubscription -ErrorAction Stop | Where-Object DisplayName -eq $tenantSubscriptionName)
$deleteVM = $vmObject | Remove-AzureRmVM -Force -ErrorAction Stop
if (-not (($deleteVM.StatusCode -eq "OK") -and ($deleteVM.IsSuccessStatusCode)))
{
Remove-AzureRmTenantSubscription -TargetSubscriptionId $subs.SubscriptionId -ErrorAction Stop
}
if ($subs = Get-AzureRmTenantSubscription -ErrorAction Stop | Where-Object DisplayName -eq $canaryDefaultTenantSubscription)
{
Remove-AzureRmTenantSubscription -TargetSubscriptionId $subs.SubscriptionId -ErrorAction Stop
}
}
Invoke-Usecase -Name 'LoginToAzureStackEnvAsSvcAdminForCleanup' -Description "Login to $SvcAdminEnvironmentName as service administrator to remove the subscription resource group" -UsecaseBlock `
{
Add-AzureRmAccount -EnvironmentName $SvcAdminEnvironmentName -Credential $ServiceAdminCredentials -TenantId $TenantID -ErrorAction Stop
}
Invoke-Usecase -Name 'DeleteSubscriptionResourceGroup' -Description "Delete the resource group that contains subscription resources" -UsecaseBlock `
{
if ($removeRG = Get-AzureRmResourceGroup -Name $subscriptionRGName -ErrorAction Stop)
{
$removeRG | Remove-AzureRmResourceGroup -Force -ErrorAction Stop
throw [System.Exception]"Failed to delete the VM $privateVMName"
}
}
}
}
}
Invoke-Usecase -Name 'DeleteVMResourceGroup' -Description "Delete the resource group that contains all the VMs and corresponding resources" -UsecaseBlock `
{
if ($removeRG = Get-AzureRmResourceGroup -Name $CanaryVMRG -ErrorAction Stop)
{
$removeRG | Remove-AzureRmResourceGroup -Force -ErrorAction Stop
}
}
Invoke-Usecase -Name 'DeleteUtilitiesResourceGroup' -Description "Delete the resource group that contains all the utilities and corresponding resources" -UsecaseBlock `
{
if ($removeRG = Get-AzureRmResourceGroup -Name $CanaryUtilitiesRG -ErrorAction Stop)
{
$removeRG | Remove-AzureRmResourceGroup -Force -ErrorAction Stop
}
}
if (($TenantAdminCredentials) -or ($listAvl))
{
Invoke-Usecase -Name 'TenantRelatedcleanup' -Description "Remove all the tenant related resources" -UsecaseBlock `
{
Invoke-Usecase -Name 'DeleteTenantSubscriptions' -Description "Remove all the tenant related subscriptions" -UsecaseBlock `
{
if ($subs = Get-AzureRmTenantSubscription -ErrorAction Stop | Where-Object DisplayName -eq $tenantSubscriptionName)
{
Remove-AzureRmTenantSubscription -TargetSubscriptionId $subs.SubscriptionId -ErrorAction Stop
}
if ($subs = Get-AzureRmTenantSubscription -ErrorAction Stop | Where-Object DisplayName -eq $canaryDefaultTenantSubscription)
{
Remove-AzureRmTenantSubscription -TargetSubscriptionId $subs.SubscriptionId -ErrorAction Stop
}
}
Invoke-Usecase -Name 'LoginToAzureStackEnvAsSvcAdminForCleanup' -Description "Login to $SvcAdminEnvironmentName as service administrator to remove the subscription resource group" -UsecaseBlock `
{
Add-AzureRmAccount -EnvironmentName $SvcAdminEnvironmentName -Credential $ServiceAdminCredentials -TenantId $TenantID -ErrorAction Stop
}
Invoke-Usecase -Name 'RemoveLinuxImageFromPIR' -Description "Remove the Linux image uploaded during setup from the Platform Image Respository" -UsecaseBlock `
{
if (Get-AzureRmVMImage -Location $ResourceLocation -PublisherName $linuxImagePublisher -Offer $linuxImageOffer -Sku $LinuxOSSku -ErrorAction SilentlyContinue)
{
Remove-AzsVMImage -publisher $linuxImagePublisher -offer $linuxImageOffer -sku $LinuxOSSku -version $linuxImageVersion -Location $ResourceLocation -Force
}
}
Invoke-Usecase -Name 'DeleteSubscriptionResourceGroup' -Description "Delete the resource group that contains subscription resources" -UsecaseBlock `
{
if ($removeRG = Get-AzureRmResourceGroup -Name $subscriptionRGName -ErrorAction Stop)
{
$removeRG | Remove-AzureRmResourceGroup -Force -ErrorAction Stop
}
}
}
}
}
}
End-Scenario
$runCount += 1
Get-CanaryResult
if (-not $ListAvailable)
{
Get-CanaryResult
}
}
if ($NumberOfIterations -gt 1)

Просмотреть файл

@ -1,7 +1,9 @@
$Global:ContinueOnFailure = $false
$Global:JSONLogFile = "Run-Canary.JSON"
$Global:TxtLogFile = "AzureStackCanaryLog.Log"
$Global:wttLogFileName= ""
$Global:ContinueOnFailure = $false
$Global:JSONLogFile = "Run-Canary.JSON"
$Global:TxtLogFile = "AzureStackCanaryLog.Log"
$Global:wttLogFileName = ""
$Global:listAvailableUsecases = $false
$Global:exclusionList = @()
if (Test-Path -Path "$PSScriptRoot\..\WTTLog.ps1")
{
Import-Module -Name "$PSScriptRoot\..\WTTLog.ps1" -Force
@ -10,7 +12,7 @@ if (Test-Path -Path "$PSScriptRoot\..\WTTLog.ps1")
$CurrentUseCase = @{}
[System.Collections.Stack] $UseCaseStack = New-Object System.Collections.Stack
filter timestamp {"$(Get-Date -Format HH:mm:ss.ffff): $_"}
filter timestamp {"$(Get-Date -Format "yyyy-MM-dd HH:mm:ss.ffff") $_"}
function Log-Info
@ -49,14 +51,11 @@ function Log-JSONReport
[string] $Message
)
if ($Message)
{
if ($Message.Contains(": ["))
{
$time = $Message.Substring(0, $Message.IndexOf(": ["))
}
{
if ($Message.Contains("[START]"))
{
$name = $Message.Substring($Message.LastIndexOf(":") + 1).Trim().Replace("######", "").Trim()
$time = $Message.Substring(0, $Message.IndexOf("[")).Trim()
$name = $Message.Substring($Message.LastIndexOf(":") + 1).Trim()
if ($UseCaseStack.Count)
{
$nestedUseCase = @{
@ -79,14 +78,19 @@ function Log-JSONReport
}
elseif ($Message.Contains("[END]"))
{
$time = $Message.Substring(0, $Message.IndexOf("[")).Trim()
$result = ""
if ($UseCaseStack.Peek().UseCase -and ($UseCaseStack.Peek().UseCase | Where-Object {$_.Result -eq "FAIL"}))
{
$result = "FAIL"
}
else
elseif ($Message.Contains("[RESULT = PASS]"))
{
$result = $Message.Substring($Message.LastIndexOf("=") + 1).Trim().Replace("] ######", "").Trim()
$result = "PASS"
}
elseif ($Message.Contains("[RESULT = FAIL]"))
{
$result = "FAIL"
}
$UseCaseStack.Peek().Add("Result", $result)
$UseCaseStack.Peek().Add("EndTime", $time)
@ -114,11 +118,53 @@ function Log-JSONReport
function Get-CanaryResult
{
$logContent = Get-Content -Raw -Path $Global:JSONLogFile | ConvertFrom-Json
Log-Info ($logContent.UseCases | Format-Table -AutoSize @{Expression = {$_.Name}; Label = "Name"; Align = "Left"},
@{Expression = {$_.Result}; Label="Result"; Align = "Left"},
@{Expression = {((Get-Date $_.EndTime) - (Get-Date $_.StartTime)).TotalSeconds}; Label = "Duration`n[Seconds]"; Align = "Left"},
@{Expression = {$_.Description}; Label = "Description"; Align = "Left"})
[CmdletBinding()]
param(
[parameter(Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[string]$LogFilename
)
if ($LogFilename)
{
$logContent = Get-Content -Raw -Path $LogFilename | ConvertFrom-Json
}
else
{
$logContent = Get-Content -Raw -Path $Global:JSONLogFile | ConvertFrom-Json
}
$results = @()
foreach ($usecase in $logContent.UseCases)
{
$ucObj = New-Object -TypeName PSObject
if ([bool]($usecase.PSobject.Properties.name -match "UseCase"))
{
$ucObj | Add-Member -Type NoteProperty -Name Name -Value $usecase.Name
$ucObj | Add-Member -Type NoteProperty -Name Result -Value $usecase.Result
$ucObj | Add-Member -Type NoteProperty -Name "Duration`n[Seconds]" -Value ((Get-Date $usecase.EndTime) - (Get-Date $usecase.StartTime)).TotalSeconds
$ucObj | Add-Member -Type NoteProperty -Name Description -Value $usecase.Description
$results += $ucObj
foreach ($subusecase in $usecase.UseCase)
{
$ucObj = New-Object -TypeName PSObject
$ucObj | Add-Member -Type NoteProperty -Name Name -Value ("|-- $($subusecase.Name)")
$ucObj | Add-Member -Type NoteProperty -Name Result -Value $subusecase.Result
$ucObj | Add-Member -Type NoteProperty -Name "Duration`n[Seconds]" -Value ((Get-Date $subusecase.EndTime) - (Get-Date $subusecase.StartTime)).TotalSeconds
$ucObj | Add-Member -Type NoteProperty -Name Description -Value ("|-- $($subusecase.Description)")
$results += $ucObj
}
}
else
{
$ucObj | Add-Member -Type NoteProperty -Name Name -Value $usecase.Name
$ucObj | Add-Member -Type NoteProperty -Name Result -Value $usecase.Result
$ucObj | Add-Member -Type NoteProperty -Name "Duration`n[Seconds]" -Value ((Get-Date $usecase.EndTime) - (Get-Date $usecase.StartTime)).TotalSeconds
$ucObj | Add-Member -Type NoteProperty -Name Description -Value $usecase.Description
$results += $ucObj
}
}
Log-Info($results | Format-Table -AutoSize)
}
function Get-CanaryLonghaulResult
@ -147,6 +193,16 @@ function Get-CanaryLonghaulResult
@{Expression={$pCount = ($_.Group | Where-Object Result -eq "PASS").Count; $times = ($_.Group | Where-Object Result -eq "PASS" | ForEach-Object {((Get-Date $_.EndTime) - (Get-Date $_.StartTime)).TotalMilliseconds}); $avgTime = ($times | Measure-Object -Average).Average; $sd = 0; foreach ($time in $times){$sd += [math]::Pow(($time - $avgTime), 2)}; [math]::Round(([math]::Round([math]::Sqrt($sd/$pCount), 0)/$avgTime), 0) * 100};Label="RelativeStdDev`n[Goal: <50%]"; Align = "Left"}
}
function Get-CanaryFailureStatus
{
$logContent = Get-Content -Raw -Path $Global:JSONLogFile | ConvertFrom-Json
if ($logContent.Usecases.Result -contains "FAIL")
{
return $true
}
return $false
}
function Start-Scenario
{
[CmdletBinding()]
@ -161,7 +217,11 @@ function Start-Scenario
[ValidateNotNullOrEmpty()]
[string]$LogFilename,
[parameter(Mandatory=$false)]
[bool] $ContinueOnFailure = $false
[bool]$ContinueOnFailure = $false,
[parameter(Mandatory=$false)]
[bool]$ListAvailable = $false,
[parameter(Mandatory=$false)]
[string[]]$ExclusionList
)
if ($LogFileName)
@ -181,14 +241,25 @@ function Start-Scenario
{
OpenWTTLogger $Global:wttLogFileName
}
New-Item -Path $Global:JSONLogFile -Type File -Force
New-Item -Path $Global:TxtLogFile -Type File -Force
$jsonReport = @{
"Scenario" = ($Name + "-" + $Type)
"UseCases" = @()
}
$jsonReport | ConvertTo-Json -Depth 10 | Out-File -FilePath $Global:JSONLogFile
if ($ListAvailable)
{
$Global:listAvailableUsecases = $true
}
if ($ExclusionList)
{
$Global:exclusionList = $ExclusionList
}
if (-not $ListAvailable)
{
New-Item -Path $Global:JSONLogFile -Type File -Force
New-Item -Path $Global:TxtLogFile -Type File -Force
$jsonReport = @{
"Scenario" = ($Name + "-" + $Type)
"UseCases" = @()
}
$jsonReport | ConvertTo-Json -Depth 10 | Out-File -FilePath $Global:JSONLogFile
}
$Global:ContinueOnFailure = $ContinueOnFailure
}
@ -214,7 +285,33 @@ function Invoke-Usecase
[ValidateNotNullOrEmpty()]
[ScriptBlock]$UsecaseBlock
)
Log-Info ("###### [START] Usecase: $Name ######`n")
if ($Global:listAvailableUsecases)
{
$parentUsecase = $Name
if ((Get-PSCallStack)[1].Arguments.Contains($parentUsecase))
{
" `t"*([math]::Floor((Get-PSCallStack).Count/3)) + "|-- " + $Name
}
else
{
"`t" + $Name
}
if ($UsecaseBlock.ToString().Contains("Invoke-Usecase"))
{
try {Invoke-Command -ScriptBlock $UsecaseBlock -ErrorAction SilentlyContinue}
catch {}
}
return
}
if (($Global:exclusionList).Contains($Name))
{
Log-Info ("Skipping Usecase: $Name")
return
}
Log-Info ("[START] Usecase: $Name`n")
if ($Global:wttLogFileName)
{
StartTest "CanaryGate:$Name"
@ -236,7 +333,7 @@ function Invoke-Usecase
{
EndTest "CanaryGate:$Name" $true
}
Log-Info ("###### [END] Usecase: $Name ###### [RESULT = PASS] ######`n")
Log-Info ("[END] [RESULT = PASS] Usecase: $Name`n")
return $result | Out-Null
}
catch [System.Exception]
@ -245,7 +342,7 @@ function Invoke-Usecase
Log-Info ("###### <FAULTING SCRIPTBLOCK> ######")
Log-Info ("$UsecaseBlock")
Log-Info ("###### </FAULTING SCRIPTBLOCK> ######")
Log-Error ("###### [END] Usecase: $Name ###### [RESULT = FAIL] ######`n")
Log-Error ("[END] [RESULT = FAIL] Usecase: $Name`n")
if ($Global:wttLogFileName)
{
EndTest "CanaryGate:$Name" $false

Просмотреть файл

@ -4,14 +4,16 @@ Canary validator provides a breadth customer experience with the Azure Stack dep
Instructions are relative to the .\CanaryValidator directory.
Canary can be invoked either as Service Administrator or Tenant Administrator.
# Download Canary
## Download Canary
```powershell
Invoke-WebRequest https://github.com/Azure/AzureStack-Tools/archive/master.zip -OutFile master.zip
Expand-Archive master.zip -DestinationPath . -Force
Set-Location -Path ".\AzureStack-Tools-master\CanaryValidator" -PassThru
```
# To execute Canary as Tenant Administrator (if Windows Server 2016 or Windows Server 2012-R2 images are already present in the PIR)
## To execute Canary as Tenant Administrator (if Windows Server 2016 or Windows Server 2012-R2 images are already present in the PIR)
```powershell
# Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
# Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
@ -21,7 +23,8 @@ $ServiceAdminCreds = New-Object System.Management.Automation.PSCredential "<Ser
.\Canary.Tests.ps1 -TenantID "<TenantID from Azure Active Directory>" -AdminArmEndpoint "<Administrative ARM endpoint>" -ServiceAdminCredentials $ServiceAdminCreds -TenantArmEndpoint "<Tenant ARM endpoint>" -TenantAdminCredentials $TenantAdminCreds
```
# To execute Canary as Tenant Administrator (if Windows Server 2016 or Windows Server 2012-R2 images are not present in PIR)
## To execute Canary as Tenant Administrator (if Windows Server 2016 or Windows Server 2012-R2 images are not present in PIR)
```powershell
# Download the WS2016 ISO image from: https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2016, and place it on your local machine
# Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
@ -32,7 +35,8 @@ $ServiceAdminCreds = New-Object System.Management.Automation.PSCredential "<Ser
.\Canary.Tests.ps1 -TenantID "<TenantID from Azure Active Directory>" -AdminArmEndpoint "<Administrative ARM endpoint>" -ServiceAdminCredentials $ServiceAdminCreds -TenantArmEndpoint "<Tenant ARM endpoint>" -TenantAdminCredentials $TenantAdminCreds -WindowsISOPath "<path where the WS2016 ISO is present>"
```
# To execute Canary as Service Administrator
## To execute Canary as Service Administrator
```powershell
# Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
# Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
@ -40,10 +44,110 @@ $ServiceAdminCreds = New-Object System.Management.Automation.PSCredential "<Ser
$ServiceAdminCreds = New-Object System.Management.Automation.PSCredential "<Service Admin username>", (ConvertTo-SecureString "<Service Admin password>" -AsPlainText -Force)
.\Canary.Tests.ps1 -TenantID "<TenantID from Azure Active Directory>" -AdminArmEndpoint "<Administrative ARM endpoint>" -ServiceAdminCredentials $ServiceAdminCreds
```
# Reading the results & logs
## To list the usecases in Canary
```powershell
# Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
# Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
# Install-Module -Name AzureStack -RequiredVersion 1.2.9 -Scope CurrentUser
.\Canary.Tests.ps1 -ListAvailable
Sample output:
PS C:\AzureStack-Tools-vnext\CanaryValidator> .\Canary.Tests.ps1 -ListAvailable
List of scenarios in Canary:
CreateAdminAzureStackEnv
LoginToAzureStackEnvAsSvcAdmin
SelectDefaultProviderSubscription
ListFabricResourceProviderInfo
|--GetAzureStackInfraRole
|--GetAzureStackInfraRoleInstance
|--GetAzureStackLogicalNetwork
|--GetAzureStackStorageCapacity
|--GetAzureStackStorageShare
|--GetAzureStackScaleUnit
|--GetAzureStackScaleUnitNode
|--GetAzureStackIPPool
|--GetAzureStackMacPool
|--GetAzureStackGatewayPool
|--GetAzureStackSLBMux
|--GetAzureStackGateway
ListHealthResourceProviderAlerts
|--GetAzureStackAlert
ListUpdatesResourceProviderInfo
|--GetAzureStackUpdateSummary
|--GetAzureStackUpdateToApply
CreateTenantAzureStackEnv
CreateResourceGroupForTenantSubscription
CreateTenantPlan
CreateTenantOffer
CreateTenantDefaultManagedSubscription
LoginToAzureStackEnvAsTenantAdmin
CreateTenantSubscription
RoleAssignmentAndCustomRoleDefinition
|--ListAssignedRoles
|--ListExistingRoleDefinitions
|--GetProviderOperations
|--AssignReaderRole
|--VerifyReaderRoleAssignment
|--RemoveReaderRoleAssignment
|--CustomRoleDefinition
|--ListRoleDefinitionsAfterCustomRoleCreation
|--RemoveCustomRoleDefinition
RegisterResourceProviders
CreateResourceGroupForUtilities
CreateStorageAccountForUtilities
CreateStorageContainerForUtilities
CreateDSCScriptResourceUtility
CreateCustomScriptResourceUtility
CreateDataDiskForVM
UploadUtilitiesToBlobStorage
CreateKeyVaultStoreForCertSecret
CreateResourceGroupForVMs
DeployARMTemplate
RetrieveResourceDeploymentTimes
QueryTheVMsDeployed
CheckVMCommunicationPreVMReboot
AddDatadiskToVMWithPrivateIP
|--StopDeallocateVMWithPrivateIPBeforeAddingDatadisk
|--AddTheDataDiskToVMWithPrivateIP
|--StartVMWithPrivateIPAfterAddingDatadisk
ApplyDataDiskCheckCustomScriptExtensionToVMWithPrivateIP
|--CheckForExistingCustomScriptExtensionOnVMWithPrivateIP
|--ApplyCustomScriptExtensionToVMWithPrivateIP
RestartVMWithPublicIP
StopDeallocateVMWithPrivateIP
StartVMWithPrivateIP
CheckVMCommunicationPostVMReboot
CheckExistenceOfScreenShotForVMWithPrivateIP
EnumerateAllResources
DeleteVMWithPrivateIP
DeleteVMResourceGroup
DeleteUtilitiesResourceGroup
TenantRelatedcleanup
|--DeleteTenantSubscriptions
|--LoginToAzureStackEnvAsSvcAdminForCleanup
|--RemoveLinuxImageFromPIR
|--DeleteSubscriptionResourceGroup
```
## To exclude certain usecases from getting executed
```powershell
# Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
# Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
# Install-Module -Name AzureStack -RequiredVersion 1.2.9 -Scope CurrentUser
# A new paramter called ExclusionList has been added which is a string array. Pass in the list of usecases you don't want to execute to this parameter.
$ServiceAdminCreds = New-Object System.Management.Automation.PSCredential "<Service Admin username>", (ConvertTo-SecureString "<Service Admin password>" -AsPlainText -Force)
.\Canary.Tests.ps1 -TenantID "<TenantID from Azure Active Directory>" -AdminArmEndpoint "<Administrative ARM endpoint>" -ServiceAdminCredentials $ServiceAdminCreds -ExclusionList "ListFabricResourceProviderInfo","ListUpdateResourceProviderInfo"
```
## Reading the results & logs
Canary generates log files in the TMP directory ($env:TMP). The logs can be found under the directory "CanaryLogs[DATETIME]". There are two types of logs generated, a text log and a JSON log. JSON log provides a quick and easy view of all the usecases and their corresponding results. Text log provides a more detailed output of each usecase execution, its output and results.
Each usecase entry in the JSON log consists of the following fields.
- Name
- Description
- StartTime
@ -51,5 +155,4 @@ Each usecase entry in the JSON log consists of the following fields.
- Result
- Exception (in case a scenario fails)
The exception field is helpful to debug failed usecases.
The exception field is helpful to debug failed use cases.

Просмотреть файл

@ -83,6 +83,12 @@
"metadata": {
"description": "Maps to the sku in the Azure Stack Platform Image Repository manifest file Eg: 12.SP1, 6.7 , 7.2"
}
},
"storageAccountEndPoint": {
"type": "string",
"metadata": {
"description": "Storage account endpoint to be used to collect the diagnostic information from the VMs"
}
}
},
@ -662,7 +668,7 @@
"protectedSettings": {
"storageAccountName": "[variables('storageAccountName3')]",
"storageAccountKey": "[listKeys(variables('storageAccountName3ID'), variables('apiVersionSRP')).key1]",
"storageAccountEndPoint": "http://azurestack.local"
"storageAccountEndPoint": "[parameters('storageAccountEndPoint')]"
}
}
},

Просмотреть файл

@ -86,6 +86,12 @@
"description": "Maps to the sku in the Azure Stack Platform Image Repository manifest file Eg: 12.SP1, 6.7 , 7.2"
},
"defaultValue": "14.04.3-LTS"
},
"storageAccountEndPoint": {
"type": "string",
"metadata": {
"description": "Storage account endpoint to be used to collect the diagnostic information from the VMs"
}
}
},
@ -561,7 +567,7 @@
"protectedSettings": {
"storageAccountName": "[variables('storageAccountName3')]",
"storageAccountKey": "[listKeys(variables('storageAccountName3ID'), variables('apiVersionSRP')).key1]",
"storageAccountEndPoint": "http://azurestack.local"
"storageAccountEndPoint": "[parameters('storageAccountEndPoint')]"
}
}
},

Просмотреть файл

@ -5,186 +5,159 @@
<#
.SYNOPSIS
Get Cloud Capabilities (ARM resources, Api-version, VM Extensions, VM Images, VMSizes etc) for Azure Stack and Azure.
#>
function Get-AzureRMCloudCapabilities()
{
[CmdletBinding()]
function Get-AzureRMCloudCapability() {
[CmdletBinding()]
[OutputType([string])]
Param(
[Parameter(HelpMessage = 'Json output file')]
[Parameter(HelpMessage = 'Json output file')]
[String] $OutputPath = "AzureCloudCapabilities.Json",
[Parameter(HelpMessage='Cloud Capabilities for the specified location')]
[String] $Location,
[Parameter(HelpMessage = 'Cloud Capabilities for the specified location')]
[String] $Location,
[Parameter(HelpMessage = 'Set this to get compute resource provider Capabilities like Extensions, Images, Sizes')]
[Switch] $IncludeComputeCapabilities,
[Parameter(HelpMessage = 'Set this to get compute resource provider Capabilities like Extensions, Images, Sizes')]
[Switch] $IncludeComputeCapabilities,
[Parameter(HelpMessage = 'Set this to get storage resource provider Capabilities like Sku')]
[Switch] $IncludeStorageCapabilities
[Parameter(HelpMessage = 'Set this to get storage resource provider Capabilities like Sku')]
[Switch] $IncludeStorageCapabilities
)
$sw = [Diagnostics.Stopwatch]::StartNew()
Write-Verbose "Getting CloudCapabilities for location: '$location'"
$providerNamespaces = (Get-AzureRmResourceProvider -ListAvailable -Location $location -ErrorAction Stop).ProviderNamespace
$resources = @()
foreach ($providerNamespace in $providerNamespaces)
{
Write-Verbose "Working on $providerNamespace provider namespace"
try
{
$resourceTypes = (Get-AzureRmResourceProvider -ProviderNamespace $providerNamespace -Location $location -ErrorAction Stop).ResourceTypes
foreach ($resourceType in $resourceTypes)
{
$result = "" | Select-Object ProviderNamespace, ResourceTypeName, Locations, ApiVersions
$result.ProviderNamespace = $providerNamespace
$result.ResourceTypeName = $resourceType.ResourceTypeName
$result.Locations = $resourceType.Locations
$result.ApiVersions = $resourceType.ApiVersions
$resources += , $result
}
}
catch
{
Write-Error "Error occurred processing $providerNamespace provider namespace.Exception: " $_.Exception.Message
}
}
$capabilities = @{}
$capabilities.Add("resources", $resources) | Out-Null
if ($IncludeComputeCapabilities)
{
Write-Verbose "Getting VMSizes for $location"
try
{
$vmSizes = (Get-AzureRmVMSize -Location $location -ErrorAction Stop| Where-Object {$_.Name -like "*"}).Name
if ($vmSizes)
{
$capabilities.Add("VMSizes", $vmSizes)
}
else
{
Write-Verbose "No VMSizes found for $location"
}
}
catch
{
Write-Error "Error occurred processing VMSizes for $location. Exception: " $_.Exception.Message
}
Write-Verbose "Getting VMImages and Extensions for location $location"
try
{
$publishers = Get-AzureRmVMImagePublisher -Location $location | Where-Object { $_.PublisherName -like "*" }
}
catch
{
Write-Error "Error occurred processing VMimagePublisher for $location. Exception: " $_.Exception.Message
}
if ($publishers)
{
$imageList = New-Object System.Collections.ArrayList
$extensionList = New-Object System.Collections.ArrayList
foreach ($publisherObj in $publishers)
{
$publisher = $publisherObj.PublisherName
$offers = Get-AzureRmVMImageOffer -Location $location -PublisherName $publisher
if ($offers -ne $null)
{
$offerList = New-Object System.Collections.ArrayList
foreach ($offerObj in $offers)
{
$offer = $offerObj.Offer
$skuList = New-Object System.Collections.ArrayList
$skus = Get-AzureRmVMImageSku -Location $location -PublisherName $publisher -Offer $offer
foreach ($skuObj in $skus)
{
$sku = $skuObj.Skus
Write-Verbose "Getting VMImage for publisher:$publisher , Offer:$offer , sku:$sku , location: $location"
$images = Get-AzureRmVMImage -Location $location -PublisherName $publisher -Offer $offer -sku $sku
$versions = $images.Version
if ($versions.Count -le 1)
{
$versions = @($versions)
}
$skuDict = @{"skuName" = $sku; "versions" = $versions}
$skuList.Add($skuDict) | Out-Null
}
$sw = [Diagnostics.Stopwatch]::StartNew()
Write-Verbose "Getting CloudCapabilities for location: '$location'"
$providerNamespaces = (Get-AzureRmResourceProvider -ListAvailable -Location $location -ErrorAction Stop).ProviderNamespace
$resources = @()
foreach ($providerNamespace in $providerNamespaces) {
Write-Verbose "Working on $providerNamespace provider namespace"
try {
$resourceTypes = (Get-AzureRmResourceProvider -ProviderNamespace $providerNamespace -Location $location -ErrorAction Stop).ResourceTypes
foreach ($resourceType in $resourceTypes) {
$result = "" | Select-Object ProviderNamespace, ResourceTypeName, Locations, ApiVersions
$result.ProviderNamespace = $providerNamespace
$result.ResourceTypeName = $resourceType.ResourceTypeName
$result.Locations = $resourceType.Locations
$result.ApiVersions = $resourceType.ApiVersions
$resources += , $result
}
}
catch {
Write-Error "Error occurred processing $providerNamespace provider namespace.Exception: " $_.Exception.Message
}
}
$offerDict = @{ "offerName" = $offer; "skus" = $skuList }
$offerList.Add($offerDict) | Out-Null
}
$capabilities = @{}
$capabilities.Add("resources", $resources) | Out-Null
$publisherDict = @{ "publisherName" = $publisher; "offers"= $offerList;"location" = $location }
$imageList.Add($publisherDict) | Out-Null
}
else
{
$types = Get-AzureRmVMExtensionImageType -Location $location -PublisherName $publisher
$typeList = New-Object System.Collections.ArrayList
if ($types -ne $null)
{
foreach ($type in $types.Type)
{
Write-Verbose "Getting VMExtension for publisher:$publisher , Type:$type , location: $location"
$extensions = Get-AzureRmVMExtensionImage -Location $location -PublisherName $publisher -Type $type
$versions = $extensions.Version
if ($versions.Count -le 1)
{
$versions = @($versions)
}
$typeDict = @{ "type" = $type; "versions" = $versions }
$typeList.Add($typeDict) | Out-Null
}
$publisherDict = @{ "publisher" = $publisher; "types" = $typeList;"location" = $location }
$extensionList.Add($publisherDict) | Out-Null
}
else
{
"none @ " + $publisher
}
}
}
$capabilities.Add("VMExtensions", $extensionList)
$capabilities.Add("VMImages", $imageList)
}
}
if ($IncludeStorageCapabilities)
{
Write-Verbose "Getting Storage Sku supported for $location"
try
{
$storageSkus = Get-AzureRmResource -ResourceType "Microsoft.Storage/Skus" -ResourceName "/"
if ($storageSkus)
{
$skuList = New-Object System.Collections.ArrayList
$storageKind = $storageSkus| Select-Object Kind | Get-Unique -AsString
foreach ($kind in $storageKind.Kind)
{
$skus= ($storageSkus | Where-Object { $_.Kind -eq $kind }).Name
$kindDict = @{ "kind" = $kind; "skus" = $skus }
$skuList.Add($kindDict) | Out-Null
}
$capabilities.Add("StorageSkus", $skuList)
}
else
{
Write-Verbose "No StorageSkus found for $location"
}
}
catch
{
Write-Error "Error occurred processing StorageSkus for $location. Exception: " $_.Exception.Message
}
}
$capabilitiesJson = ConvertTo-Json $capabilities -Depth 10
$capabilitiesJson | Out-File $OutputPath
if ($IncludeComputeCapabilities) {
Write-Verbose "Getting VMSizes for $location"
try {
$vmSizes = (Get-AzureRmVMSize -Location $location -ErrorAction Stop| Where-Object {$_.Name -like "*"}).Name
if ($vmSizes) {
$capabilities.Add("VMSizes", $vmSizes)
}
else {
Write-Verbose "No VMSizes found for $location"
}
}
catch {
Write-Error "Error occurred processing VMSizes for $location. Exception: " $_.Exception.Message
}
$sw.Stop()
$time = $sw.Elapsed
"Cloud Capabilities JSON Generation Complete"
"Time Elapsed = " + [math]::floor($time.TotalMinutes) + " min " + $time.Seconds + " sec"
Write-Verbose "Getting VMImages and Extensions for location $location"
try {
$publishers = Get-AzureRmVMImagePublisher -Location $location | Where-Object { $_.PublisherName -like "*" }
}
catch {
Write-Error "Error occurred processing VMimagePublisher for $location. Exception: " $_.Exception.Message
}
if ($publishers) {
$imageList = New-Object System.Collections.ArrayList
$extensionList = New-Object System.Collections.ArrayList
foreach ($publisherObj in $publishers) {
$publisher = $publisherObj.PublisherName
$offers = Get-AzureRmVMImageOffer -Location $location -PublisherName $publisher
if ($offers) {
$offerList = New-Object System.Collections.ArrayList
foreach ($offerObj in $offers) {
$offer = $offerObj.Offer
$skuList = New-Object System.Collections.ArrayList
$skus = Get-AzureRmVMImageSku -Location $location -PublisherName $publisher -Offer $offer
foreach ($skuObj in $skus) {
$sku = $skuObj.Skus
Write-Verbose "Getting VMImage for publisher:$publisher , Offer:$offer , sku:$sku , location: $location"
$images = Get-AzureRmVMImage -Location $location -PublisherName $publisher -Offer $offer -sku $sku
$versions = $images.Version
if ($versions.Count -le 1) {
$versions = @($versions)
}
$skuDict = @{"skuName" = $sku; "versions" = $versions}
$skuList.Add($skuDict) | Out-Null
}
$offerDict = @{ "offerName" = $offer; "skus" = $skuList }
$offerList.Add($offerDict) | Out-Null
}
$publisherDict = @{ "publisherName" = $publisher; "offers" = $offerList; "location" = $location }
$imageList.Add($publisherDict) | Out-Null
}
else {
$types = Get-AzureRmVMExtensionImageType -Location $location -PublisherName $publisher
$typeList = New-Object System.Collections.ArrayList
if ($types) {
foreach ($type in $types.Type) {
Write-Verbose "Getting VMExtension for publisher:$publisher , Type:$type , location: $location"
$extensions = Get-AzureRmVMExtensionImage -Location $location -PublisherName $publisher -Type $type
$versions = $extensions.Version
if ($versions.Count -le 1) {
$versions = @($versions)
}
$typeDict = @{ "type" = $type; "versions" = $versions }
$typeList.Add($typeDict) | Out-Null
}
$publisherDict = @{ "publisher" = $publisher; "types" = $typeList; "location" = $location }
$extensionList.Add($publisherDict) | Out-Null
}
else {
"none @ " + $publisher
}
}
}
$capabilities.Add("VMExtensions", $extensionList)
$capabilities.Add("VMImages", $imageList)
}
}
if ($IncludeStorageCapabilities) {
Write-Verbose "Getting Storage Sku supported for $location"
try {
$storageSkus = Get-AzureRmResource -ResourceType "Microsoft.Storage/Skus" -ResourceName "/"
if ($storageSkus) {
$skuList = New-Object System.Collections.ArrayList
$storageKind = $storageSkus| Select-Object Kind | Get-Unique -AsString
foreach ($kind in $storageKind.Kind) {
$skus = ($storageSkus | Where-Object { $_.Kind -eq $kind }).Name
$kindDict = @{ "kind" = $kind; "skus" = $skus }
$skuList.Add($kindDict) | Out-Null
}
$capabilities.Add("StorageSkus", $skuList)
}
else {
Write-Verbose "No StorageSkus found for $location"
}
}
catch {
Write-Error "Error occurred processing StorageSkus for $location. Exception: " $_.Exception.Message
}
}
$capabilitiesJson = ConvertTo-Json $capabilities -Depth 10
$capabilitiesJson | Out-File $OutputPath
$sw.Stop()
$time = $sw.Elapsed
"Cloud Capabilities JSON Generation Complete"
"Time Elapsed = " + [math]::floor($time.TotalMinutes) + " min " + $time.Seconds + " sec"
}

Просмотреть файл

@ -1,11 +1,16 @@
# Get Cloud Capabilities
Instructions below are relative to the .\CloudCapabilities folder of the [AzureStack-Tools repo](..).
To get VMImages, Extensions & Sizes available in the cloud, add -IncludeComputeCapabilities
To get StorageSkus available in the cloud, add -IncludeStorageCapabilities
```powershell
Import-Module ".\AzureRM.CloudCapabilities.psm1"
```
# Prerequisites
## Prerequisites
Connected Azure or AzureStack powershell environment (Refer [AzureStack-Tools repo/Connect](../Connect) for connecting to an Azure Stack instance. )
```powershell

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Двоичные данные
ComputeAdmin/ComputeAdmin.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 418 KiB

Просмотреть файл

@ -1,4 +1,7 @@
# Azure Stack Compute Administration
![Adding an image in an ADFS environment](/ComputeAdmin/ComputeAdmin.gif)
Instructions below are relative to the .\ComputeAdmin folder of the [AzureStack-Tools repo](..).
Make sure you have the following module prerequisites installed:
@ -6,45 +9,53 @@ Make sure you have the following module prerequisites installed:
```powershell
Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.9 -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.10 -Scope CurrentUser
```
Then make sure the following modules are imported:
```powershell
Import-Module ..\Connect\AzureStack.Connect.psm1
Import-Module .\AzureStack.ComputeAdmin.psm1
```
You will need to reference your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
## Add PowerShell environment
You will need to login to your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
```powershell
Add-AzureStackAzureRmEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
Add-AzureRMEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
```
Adding a VM Image requires that you obtain the value of your Directory Tenant ID. For **Azure Active Directory** environments provide your directory tenant name:
Then login:
```powershell
$TenantID = Get-DirectoryTenantID -AADTenantName "<mydirectorytenant>.onmicrosoft.com" -EnvironmentName AzureStackAdmin
Login-AzureRmAccount -EnvironmentName "AzureStackAdmin"
```
----
If you are **not** using your home directory tenant, you will need to supply the tenant ID to your login command. You may find it easiest to obtain using the Connect tool. For **Azure Active Directory** environments provide your directory tenant name:
```powershell
$TenantID = Get-AzsDirectoryTenantId -AADTenantName "<mydirectorytenant>.onmicrosoft.com" -EnvironmentName AzureStackAdmin
```
For **ADFS** environments use the following:
```powershell
$TenantID = Get-DirectoryTenantID -ADFS -EnvironmentName AzureStackAdmin
$TenantID = Get-AzsDirectoryTenantId -ADFS -EnvironmentName AzureStackAdmin
```
## Add the WS2016 Evaluation VM Image
The New-Server2016VMImage allows you to add a Windows Server 2016 Evaluation VM Image to your Azure Stack Marketplace.
The New-AzsServer2016VMImage allows you to add a Windows Server 2016 Evaluation VM Image to your Azure Stack Marketplace.
As a prerequisite, you need to obtain the Windows Server 2016 Evaluation ISO which can be found [here](https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2016).
An example usage is the following:
```powershell
$ISOPath = "<Path to ISO>"
New-Server2016VMImage -ISOPath $ISOPath -TenantId $TenantID -EnvironmentName "AzureStackAdmin"
New-AzsServer2016VMImage -ISOPath $ISOPath
```
Please make sure to specify the correct administrator ARM endpoint for your environment.
This command may show a **popup prompt that can be ignored** without issue.
@ -55,31 +66,25 @@ Please note that to use this image for **installing additional Azure Stack servi
## Add a VM image to the Marketplace with PowerShell
1. Prepare a Windows or Linux operating system virtual hard disk image in VHD format (not VHDX).
- For Windows images, the article [Upload a Windows VM image to Azure for Resource Manager deployments](https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-windows-upload-image/) contains image preparation instructions in the **Prepare the VHD for upload** section.
- For Linux images, follow the steps to
- For Windows images, the article [Upload a Windows VM image to Azure for Resource Manager deployments](https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-windows-upload-image/) contains image preparation instructions in the **Prepare the VHD for upload** section.
- For Linux images, follow the steps to
prepare the image or use an existing Azure Stack Linux image as described in
the article [Deploy Linux virtual machines on Azure
Stack](https://azure.microsoft.com/en-us/documentation/articles/azure-stack-linux/).
2. Add the VM image by invoking the Add-VMImage cmdlet.
- Include the publisher, offer, SKU, and version for the VM image. These parameters are used by Azure Resource Manager templates that reference the VM image.
- Specify osType as Windows or Linux.
- Include your Azure Active Directory tenant ID in the form *&lt;mydirectory&gt;*.onmicrosoft.com.
- The following is an example invocation of the script:
1. Add the VM image by invoking the Add-AzsVMImage cmdlet.
You will need to reference your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
- Include the publisher, offer, SKU, and version for the VM image. These parameters are used by Azure Resource Manager templates that reference the VM image.
- Specify osType as Windows or Linux.
- The following is an example invocation of the script:
```powershell
Add-AzureStackAzureRmEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
Add-AzsVMImage -publisher "Canonical" -offer "UbuntuServer" -sku "14.04.3-LTS" -version "1.0.0" -osType Linux -osDiskLocalPath 'C:\Users\<me>\Desktop\UbuntuServer.vhd'
```
```powershell
Add-VMImage -publisher "Canonical" -offer "UbuntuServer" -sku "14.04.3-LTS" -version "1.0.0" -osType Linux -osDiskLocalPath 'C:\Users\<me>\Desktop\UbuntuServer.vhd' -tenantID <GUID AADTenant> -EnvironmentName "AzureStackAdmin"
```
Note: The cmdlet requests credentials for adding the VM image. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Uploads the local VHD to a newly created temporary storage account
- Adds the VM image to the VM image repository
@ -88,79 +93,49 @@ The command does the following:
To verify that the command ran successfully, go to Marketplace in the portal, and then verify that the VM image is available in the **Virtual Machines** category.
## Remove a VM Image with PowerShell
Run the below command to remove an uploaded VM image. After removal, tenants will no longer be able to deploy virtual machines with this image.
You will need to reference your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
```powershell
Add-AzureStackAzureRmEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
```
```powershell
Remove-VMImage -publisher "Canonical" -offer "UbuntuServer" -sku "14.04.3-LTS" -version "1.0.0" -tenantID <GUID AADTenant> -EnvironmentName "AzureStackAdmin"
Remove-AzsVMImage -publisher "Canonical" -offer "UbuntuServer" -sku "14.04.3-LTS" -version "1.0.0"
```
Note: This cmdlet will remove the associated Marketplace item unless the -KeepMarketplaceItem parameter is specified.
## Add a VM extension to the Compute with PowerShell
You will need to reference your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
```powershell
Add-AzureStackAzureRmEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
```
An example usage is the following:
```powershell
$path = "<Path to vm extension zip>"
Add-VMExtension -publisher "Publisher" -type "Type" -version "1.0.0.0" -extensionLocalPath $path -osType Windows -tenantID $TenantID -azureStackCredentials $azureStackCredentials -EnvironmentName "AzureStackAdmin"
```
# Remove a VM extension with PowerShell
You will need to reference your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
```powershell
Add-AzureStackAzureRmEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
```
Run the below command to remove an uploaded VM extension.
```powershell
Remove-VMExtension -publisher "Publisher" -type "Type" -version "1.0.0.0" -osType Windows -tenantID $TenantID -azureStackCredentials $azureStackCredentials -EnvironmentName "AzureStackAdmin"
```
## VM Scale Set gallery item
VM Scale Set allows deployment of multi-VM collections. To add a gallery item with VM Scale Set:
1. Add evaluation Windows Server 2016 image using New-Server2016VMImage as described above.
1. Add evaluation Windows Server 2016 image using New-AzsServer2016VMImage as described above.
2. For linux support, download Ubuntu Server 16.04 and add it using Add-VmImage with the following parameters -publisher "Canonical" -offer "UbuntuServer" -sku "16.04-LTS"
1. For linux support, download Ubuntu Server 16.04 and add it using Add-AzsVMImage with the following parameters -publisher "Canonical" -offer "UbuntuServer" -sku "16.04-LTS"
3. Add VM Scale Set gallery item as follows
1. Add VM Scale Set gallery item as follows
```powershell
$TenantId = "<AAD Tenant Id used to connect to AzureStack>"
$Arm = "<AzureStack administrative Azure Resource Manager endpoint URL>"
$Location = "<The location name of your AzureStack Environment>"
Add-AzureStackAzureRmEnvironment -Name AzureStackAdmin -ArmEndpoint $Arm
Add-AzsEnvironment -Name AzureStackAdmin -ArmEndpoint $Arm
$Password = ConvertTo-SecureString -AsPlainText -Force "<your AzureStack admin user password>"
$User = "<your AzureStack admin user name>"
$Creds = New-Object System.Management.Automation.PSCredential $User, $Password
Login-AzureRmAccount -EnvironmentName AzureStackAdmin -Credential $Creds -TenantId $TenantId
$AzsEnv = Get-AzureRmEnvironment AzureStackAdmin
$AzsEnvContext = Add-AzureRmAccount -Environment $AzsEnv -Credential $Creds
Select-AzureRmProfile -Profile $AzsEnvContext
Select-AzureRmSubscription -SubscriptionName "Default Provider Subscription"
Add-AzureStackVMSSGalleryItem -Location $Location
```
Add-AzsVMSSGalleryItem -Location $Location
To remove VM Scale Set gallery item run the following command:
```powershell
Remove-AzureStackVMSSGalleryItem
Remove-AzsVMSSGalleryItem
```
Note that gallery item is not removed immediately. You could run the above command several times to determine when the item is actually gone.

Просмотреть файл

@ -11,13 +11,13 @@ Describe $script:ModuleName {
Should Not Be $null
}
It 'Add-VMImage should be exported' {
Get-Command -Name Add-VMImage -ErrorAction SilentlyContinue |
It 'Add-AzsVMImage should be exported' {
Get-Command -Name Add-AzsVMImage -ErrorAction SilentlyContinue |
Should Not Be $null
}
It 'Remove-VMImage should be exported' {
Get-Command -Name Remove-VMImage -ErrorAction SilentlyContinue |
It 'Remove-AzsVMImage should be exported' {
Get-Command -Name Remove-AzsVMImage -ErrorAction SilentlyContinue |
Should Not Be $null
}
}
@ -28,17 +28,11 @@ InModuleScope $script:ModuleName {
$HostComputer = $global:HostComputer
$ArmEndpoint = $global:ArmEndpoint
$natServer = $global:natServer
$AdminUser= $global:AdminUser
$AdminUser = $global:AdminUser
$AadServiceAdmin = $global:AadServiceAdmin
$AdminPassword = $global:AdminPassword
$AadServiceAdminPassword = $global:AadServiceAdminPassword
$stackLoginCreds = $global:AzureStackLoginCredentials
$VPNConnectionName = $global:VPNConnectionName
$AadTenant = $global:AadTenantID
$EnvironmentName = $global:EnvironmentName
# Generate Fake VHD for testing image upload
@ -59,38 +53,38 @@ InModuleScope $script:ModuleName {
Describe 'ComputeAdmin - Functional Tests' {
It 'CreateGalleryItem = "$false" -and title = specified should throw' {
{ Add-VMImage -publisher $publisher -offer $offer -sku $sku -version $version -osType $osType -osDiskLocalPath $osDiskPath -tenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredential $stackLoginCreds -CreateGalleryItem $false -title 'testTitle' } |
{ Add-AzsVMImage -publisher $publisher -offer $offer -sku $sku -version $version -osType $osType -osDiskLocalPath $osDiskPath -CreateGalleryItem $false -title 'testTitle' } |
Should Throw
}
It 'CreateGalleryItem = "$false" -and description = specified should throw' {
{ Add-VMImage -publisher $publisher -offer $offer -sku $sku -version $version -osType $osType -osDiskLocalPath $osDiskPath -tenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredential $stackLoginCreds -CreateGalleryItem $false -title 'testTitle' -CreateGalleryItem $false -description 'testdescription' } | Should Throw
{ Add-AzsVMImage -publisher $publisher -offer $offer -sku $sku -version $version -osType $osType -osDiskLocalPath $osDiskPath -CreateGalleryItem $false -title 'testTitle' -CreateGalleryItem $false -description 'testdescription' } | Should Throw
}
It 'Add-VMImage via local path and upload to storage account should succeed' {
{ Add-VMImage -publisher $publisher -offer $offer -sku $sku -version $version -osType $osType -osDiskLocalPath $osDiskPath -tenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredential $stackLoginCreds -CreateGalleryItem $false } |
It 'Add-AzsVMImage via local path and upload to storage account should succeed' {
{ Add-AzsVMImage -publisher $publisher -offer $offer -sku $sku -version $version -osType $osType -osDiskLocalPath $osDiskPath -CreateGalleryItem $false } |
Should Not Throw
}
It 'Remove-VMImage should successfully remove added VM Image' {
{ Remove-VMImage -publisher $publisher -offer $offer -sku $sku -version $version -tenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredential $stackLoginCreds} |
It 'Remove-AzsVMImage should successfully remove added VM Image' {
{ Remove-AzsVMImage -publisher $publisher -offer $offer -sku $sku -version $version} |
Should Not Throw
}
It 'Add-VMImage via local path and upload to storage account with gallery item should succeed' {
{ Add-VMImage -publisher $publisher -offer $offer -sku $gallerySku -version $version -osType $osType -osDiskLocalPath $osDiskPath -tenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredential $stackLoginCreds } |
It 'Add-AzsVMImage via local path and upload to storage account with gallery item should succeed' {
{ Add-AzsVMImage -publisher $publisher -offer $offer -sku $gallerySku -version $version -osType $osType -osDiskLocalPath $osDiskPath } |
Should Not Throw
}
It 'Remove-VMImage and Removing Marketplace Item should successfully complete' {
It 'Remove-AzsVMImage and Removing Marketplace Item should successfully complete' {
{
Remove-VMImage -publisher $publisher -offer $offer -sku $gallerySku -version $version -tenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredential $stackLoginCreds
Remove-AzsVMImage -publisher $publisher -offer $offer -sku $gallerySku -version $version
Get-AzureRMGalleryItem | Where-Object {$_.Name -contains "$publisher.$offer$gallerySku.$version"} | Remove-AzureRMGalleryItem
} | Should Not Throw
}
It 'Adding Ubuntu Linux 16.04 Image and Marketplace Item Succeeds' {
{ Add-VMImage -publisher "Canonical" -offer "UbuntuServer" -sku "16.04.1-LTS" -version "1.0.4" -osType Linux -EnvironmentName $EnvironmentName -osDiskLocalPath $ubuntuPath -tenantID $AadTenant -AzureStackCredential $stackLoginCreds} |
{ Add-AzsVMImage -publisher "Canonical" -offer "UbuntuServer" -sku "16.04.1-LTS" -version "1.0.4" -osType Linux -osDiskLocalPath $ubuntuPath} |
Should Not Throw
}
@ -100,9 +94,10 @@ InModuleScope $script:ModuleName {
$newOffer = "UbuntuServer"
$newSKU = "16.04.1-LTS"
$newVersion = "1.0.4"
Remove-VMImage -publisher $newPub -offer $newOffer -sku $newSKU -version $newVersion -tenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredential $stackLoginCreds
Remove-AzsVMImage -publisher $newPub -offer $newOffer -sku $newSKU -version $newVersion
$GalleryItemName = "$newOffer$newSKU"
$GalleryItemName = $GalleryItemName -replace "\.","-"
$GalleryItemName = $GalleryItemName -replace "\.", "-"
Get-AzureRMGalleryItem | Where-Object {$_.Name -contains "$newPub.$GalleryItemName.$newVersion"} | Remove-AzureRMGalleryItem
} | Should Not Throw
}
@ -112,4 +107,4 @@ InModuleScope $script:ModuleName {
Remove-Item $ubuntuPath
Remove-Item $osDiskPath
Remove-Item $dataDiskPath
}
}

Просмотреть файл

@ -4,198 +4,25 @@
#requires -Version 4.0
#requires -Modules AzureRM.Profile, VpnClient, AzureRM.AzureStackAdmin
<#
.SYNOPSIS
Registers all providers on the all subscription
#>
function Register-AllAzureRmProvidersOnAllSubscriptions {
foreach($s in (Get-AzureRmSubscription)) {
Select-AzureRmSubscription -SubscriptionId $s.SubscriptionId | Out-Null
Write-Progress $($s.SubscriptionId + " : " + $s.SubscriptionName)
Register-AllAzureRmProviders
}
}
Export-ModuleMember Register-AllAzureRmProvidersOnAllSubscriptions
<#
.SYNOPSIS
Registers all providers on the newly created subscription
#>
function Register-AllAzureRmProviders {
Get-AzureRmResourceProvider -ListAvailable | Register-AzureRmResourceProvider -Force
}
Export-ModuleMember Register-AllAzureRmProviders
<#
.SYNOPSIS
Obtains Aazure Active Directory tenant that was used when deploying the Azure Stack instance
#>
function Get-AzureStackAadTenant {
param (
[parameter(mandatory=$true, HelpMessage="Azure Stack One Node host address or name such as '1.2.3.4'")]
[string] $HostComputer,
[Parameter(HelpMessage="The Domain suffix of the environment VMs")]
[string] $DomainSuffix = 'azurestack.local',
[parameter(HelpMessage="Administrator user name of this Azure Stack Instance")]
[string] $User = "administrator",
[parameter(mandatory=$true, HelpMessage="Administrator password used to deploy this Azure Stack instance")]
[securestring] $Password
)
$Domain = $DomainSuffix
$UserCred = "$Domain\$User"
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $UserCred, $Password
Write-Verbose "Remoting to the Azure Stack host $HostComputer..." -Verbose
return Invoke-Command -ComputerName "$HostComputer" -Credential $credential -ScriptBlock `
{
Write-Verbose "Retrieving Azure Stack configuration..." -Verbose
$configFile = Get-ChildItem -Path C:\EceStore -Recurse | Where-Object {-not $_.PSIsContainer} | Sort-Object Length -Descending | Select-Object -First 1
$customerConfig = [xml] (Get-Content -Path $configFile.FullName)
$Parameters = $customerConfig.CustomerConfiguration
$fabricRole = $Parameters.Role.Roles.Role | Where-Object {$_.Id -eq "Fabric"}
$allFabricRoles = $fabricRole.Roles.ChildNodes
$idProviderRole = $allFabricRoles | Where-Object {$_.Id -eq "IdentityProvider"}
$idProviderRole.PublicInfo.AADTenant.Id
}
}
Export-ModuleMember Get-AzureStackAadTenant
<#
.SYNOPSIS
Adds Azure Stack environment to use with AzureRM command-lets when targeting Azure Stack
#>
function Add-AzureStackAzureRmEnvironment {
param (
[Parameter(mandatory=$true, HelpMessage="The Admin ARM endpoint of the Azure Stack Environment")]
[string] $ArmEndpoint,
[parameter(mandatory=$true, HelpMessage="Azure Stack environment name for use with AzureRM commandlets")]
[string] $Name
)
if(!$ARMEndpoint.Contains('https://')){
if($ARMEndpoint.Contains('http://')){
$ARMEndpoint = $ARMEndpoint.Substring(7)
$ARMEndpoint = 'https://' + $ARMEndpoint
}else{
$ARMEndpoint = 'https://' + $ARMEndpoint
}
}
$ArmEndpoint = $ArmEndpoint.TrimEnd("/")
$Domain = ""
try {
$uriARMEndpoint = [System.Uri] $ArmEndpoint
$i = $ArmEndpoint.IndexOf('.')
$Domain = ($ArmEndpoint.Remove(0,$i+1)).TrimEnd('/')
}
catch {
Write-Error "The specified ARM endpoint was invalid"
}
$ResourceManagerEndpoint = $ArmEndpoint
$stackdomain = $Domain
Write-Verbose "Retrieving endpoints from the $ResourceManagerEndpoint..." -Verbose
$endpoints = Invoke-RestMethod -Method Get -Uri "$($ResourceManagerEndpoint.ToString().TrimEnd('/'))/metadata/endpoints?api-version=2015-01-01" -ErrorAction Stop
$AzureKeyVaultDnsSuffix="vault.$($stackdomain)".ToLowerInvariant()
$AzureKeyVaultServiceEndpointResourceId= $("https://vault.$stackdomain".ToLowerInvariant())
$StorageEndpointSuffix = ($stackdomain).ToLowerInvariant()
$aadAuthorityEndpoint = $endpoints.authentication.loginEndpoint
$azureEnvironmentParams = @{
Name = $Name
ActiveDirectoryEndpoint = $endpoints.authentication.loginEndpoint.TrimEnd('/') + "/"
ActiveDirectoryServiceEndpointResourceId = $endpoints.authentication.audiences[0]
ResourceManagerEndpoint = $ResourceManagerEndpoint
GalleryEndpoint = $endpoints.galleryEndpoint
GraphEndpoint = $endpoints.graphEndpoint
GraphAudience = $endpoints.graphEndpoint
StorageEndpointSuffix = $StorageEndpointSuffix
AzureKeyVaultDnsSuffix = $AzureKeyVaultDnsSuffix
AzureKeyVaultServiceEndpointResourceId = $AzureKeyVaultServiceEndpointResourceId
EnableAdfsAuthentication = $aadAuthorityEndpoint.TrimEnd("/").EndsWith("/adfs", [System.StringComparison]::OrdinalIgnoreCase)
}
$armEnv = Get-AzureRmEnvironment -Name $Name
if($armEnv -ne $null) {
Write-Verbose "Updating AzureRm environment $Name" -Verbose
Remove-AzureRmEnvironment -Name $Name -Force | Out-Null
}
else {
Write-Verbose "Adding AzureRm environment $Name" -Verbose
}
return Add-AzureRmEnvironment @azureEnvironmentParams
}
Export-ModuleMember Add-AzureStackAzureRmEnvironment
<#
.SYNOPSIS
Obtains Azure Stack NAT address from the Azure Stack One Node instance
#>
function Get-AzureStackNatServerAddress {
param (
[parameter(mandatory=$true, HelpMessage="Azure Stack One Node host address or name such as '1.2.3.4'")]
[string] $HostComputer,
[Parameter(HelpMessage="The Domain suffix of the environment VMs")]
[string] $DomainSuffix = 'azurestack.local',
[parameter(HelpMessage="NAT computer name in this Azure Stack Instance")]
[string] $natServer = "mas-bgpnat01",
[parameter(HelpMessage="Administrator user name of this Azure Stack Instance")]
[string] $User = "administrator",
[parameter(mandatory=$true, HelpMessage="Administrator password used to deploy this Azure Stack instance")]
[securestring] $Password
)
$Domain = $DomainSuffix
$UserCred = "$Domain\$User"
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $UserCred, $Password
$nat = "$natServer.$Domain"
Write-Verbose "Remoting to the Azure Stack host $HostComputer..." -Verbose
return Invoke-Command -ComputerName "$HostComputer" -Credential $credential -ScriptBlock `
{
Write-Verbose "Remoting to the Azure Stack NAT server $using:nat..." -Verbose
Invoke-Command -ComputerName "$using:nat" -Credential $using:credential -ScriptBlock `
{
Write-Verbose "Obtaining external IP..." -Verbose
Get-NetIPConfiguration | Where-Object { $_.IPv4DefaultGateway -ne $null } | ForEach-Object { $_.IPv4Address.IPAddress }
}
}
}
Export-ModuleMember Get-AzureStackNatServerAddress
<#
.SYNOPSIS
Add VPN connection to an Azure Stack instance
#>
function Add-AzureStackVpnConnection {
function Add-AzsVpnConnection {
param (
[parameter(HelpMessage="Azure Stack VPN Connection Name such as 'my-poc'")]
[parameter(HelpMessage = "Azure Stack VPN Connection Name such as 'my-poc'")]
[string] $ConnectionName = "azurestack",
[parameter(mandatory=$true, HelpMessage="External IP of the Azure Stack NAT VM such as '1.2.3.4'")]
[parameter(mandatory = $true, HelpMessage = "External IP of the Azure Stack NAT VM such as '1.2.3.4'")]
[string] $ServerAddress,
[parameter(mandatory=$true, HelpMessage="Administrator password used to deploy this Azure Stack instance")]
[parameter(mandatory = $true, HelpMessage = "Administrator password used to deploy this Azure Stack instance")]
[securestring] $Password
)
$existingConnection = Get-VpnConnection -Name $ConnectionName -ErrorAction Ignore
if ($existingConnection -ne $null) {
if ($existingConnection) {
Write-Verbose "Updating Azure Stack VPN connection named $ConnectionName" -Verbose
rasdial $ConnectionName /d
Remove-VpnConnection -name $ConnectionName -Force -ErrorAction Ignore
@ -216,28 +43,25 @@ function Add-AzureStackVpnConnection {
return $connection
}
Export-ModuleMember Add-AzureStackVpnConnection
Export-ModuleMember -Function 'Add-AzsVpnConnection'
<#
.SYNOPSIS
Connects to Azure Stack via VPN
#>
function Connect-AzureStackVpn {
function Connect-AzsVpn {
param (
[parameter(HelpMessage="Azure Stack VPN Connection Name such as 'my-poc'")]
[parameter(HelpMessage = "Azure Stack VPN Connection Name such as 'my-poc'")]
[string] $ConnectionName = "azurestack",
[Parameter(HelpMessage="The Domain suffix of the environment VMs")]
[string] $DomainSuffix = 'azurestack.local',
[parameter(HelpMessage="Certificate Authority computer name in this Azure Stack Instance")]
[string] $Remote = "mas-ca01",
[parameter(HelpMessage="Administrator user name of this Azure Stack Instance")]
[parameter(HelpMessage = "Administrator user name of this Azure Stack Instance")]
[string] $User = "administrator",
[parameter(mandatory=$true, HelpMessage="Administrator password used to deploy this Azure Stack instance")]
[securestring] $Password
[parameter(mandatory = $true, HelpMessage = "Administrator password used to deploy this Azure Stack instance")]
[securestring] $Password,
[parameter(HelpMessage = "Indicate whether to retrieve and trust certificates from the environment after establishing a VPN connection")]
[bool] $RetrieveCertificates = $true
)
$Domain = $DomainSuffix
Write-Verbose "Connecting to Azure Stack VPN using connection named $ConnectionName..." -Verbose
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
@ -248,150 +72,73 @@ function Connect-AzureStackVpn {
$azshome = "$env:USERPROFILE\Documents\$ConnectionName"
Write-Verbose "Connection-specific files will be saved in $azshome" -Verbose
if ($RetrieveCertificates) {
Write-Verbose "Connection-specific files will be saved in $azshome" -Verbose
New-Item $azshome -ItemType Directory -Force | Out-Null
New-Item $azshome -ItemType Directory -Force | Out-Null
$UserCred = "$Domain\$User"
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $UserCred, $Password
$hostIP = (Get-VpnConnection -Name $ConnectionName).ServerAddress
Write-Verbose "Retrieving Azure Stack Root Authority certificate..." -Verbose
$cert = Invoke-Command -ComputerName "$Remote.$Domain" -ScriptBlock { Get-ChildItem cert:\currentuser\root | where-object {$_.Subject -eq "CN=AzureStackCertificationAuthority, DC=AzureStack, DC=local"} } -Credential $credential
$UserCred = ".\$User"
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $UserCred, $Password
if($cert -ne $null) {
if($cert.GetType().IsArray) {
$cert = $cert[0] # take any that match the subject if multiple certs were deployed
Write-Verbose "Retrieving Azure Stack Root Authority certificate..." -Verbose
$cert = Invoke-Command -ComputerName "$hostIP" -ScriptBlock { Get-ChildItem cert:\currentuser\root | where-object {$_.Subject -like "*AzureStackSelfSignedRootCert*"} } -Credential $credential
if ($cert) {
if ($cert.GetType().IsArray) {
$cert = $cert[0] # take any that match the subject if multiple certs were deployed
}
$certFilePath = "$azshome\CA.cer"
Write-Verbose "Saving Azure Stack Root certificate in $certFilePath..." -Verbose
Export-Certificate -Cert $cert -FilePath $certFilePath -Force | Out-Null
Write-Verbose "Installing Azure Stack Root certificate for the current user..." -Verbose
Write-Progress "LOOK FOR CERT ACCEPTANCE PROMPT ON YOUR SCREEN!"
Import-Certificate -CertStoreLocation cert:\currentuser\root -FilePath $certFilePath
}
else {
Write-Error "Certificate has not been retrieved!"
}
$certFilePath = "$azshome\CA.cer"
Write-Verbose "Saving Azure Stack Root certificate in $certFilePath..." -Verbose
Export-Certificate -Cert $cert -FilePath $certFilePath -Force | Out-Null
Write-Verbose "Installing Azure Stack Root certificate for the current user..." -Verbose
Write-Progress "LOOK FOR CERT ACCEPTANCE PROMPT ON YOUR SCREEN!"
Import-Certificate -CertStoreLocation cert:\currentuser\root -FilePath $certFilePath
}
else {
Write-Error "Certificate has not been retrieved!"
}
}
Export-ModuleMember Connect-AzureStackVpn
Export-ModuleMember -Function 'Connect-AzsVpn'
<#
.SYNOPSIS
Retrieve the admin token and subscription ID needed to make REST calls directly to Azure Resource Manager
Connecting to your environment requires that you obtain the value of your Directory Tenant ID.
For **Azure Active Directory** environments provide your directory tenant name.
#>
function Get-AzureStackAdminSubTokenHeader {
param (
[parameter(mandatory=$true, HelpMessage="Name of the Azure Stack Environment")]
[string] $EnvironmentName,
[parameter(mandatory=$true, HelpMessage="TenantID of Identity Tenant")]
[string] $tenantID,
[parameter(HelpMessage="Credentials to retrieve token header for")]
[System.Management.Automation.PSCredential] $azureStackCredentials,
[parameter(HelpMessage="Name of the Administrator subscription")]
[string] $subscriptionName = "Default Provider Subscription"
)
$azureStackEnvironment = Get-AzureRmEnvironment -Name $EnvironmentName -ErrorAction SilentlyContinue
if($azureStackEnvironment -ne $null) {
$ARMEndpoint = $azureStackEnvironment.ResourceManagerUrl
}
else {
Write-Error "The Azure Stack Admin environment with the name $EnvironmentName does not exist. Create one with Add-AzureStackAzureRmEnvironment." -ErrorAction Stop
}
if(-not $azureStackCredentials){
$azureStackCredentials = Get-Credential
}
try{
Invoke-RestMethod -Method Get -Uri "$($ARMEndpoint.ToString().TrimEnd('/'))/metadata/endpoints?api-version=2015-01-01" -ErrorAction Stop | Out-Null
}catch{
Write-Error "The specified ARM endpoint: $ArmEndpoint is not valid for this environment. Please make sure you are using the correct administrator ARM endpoint for this environment." -ErrorAction Stop
}
$authority = $azureStackEnvironment.ActiveDirectoryAuthority
$activeDirectoryServiceEndpointResourceId = $azureStackEnvironment.ActiveDirectoryServiceEndpointResourceId
Login-AzureRmAccount -EnvironmentName $EnvironmentName -TenantId $tenantID -Credential $azureStackCredentials | Out-Null
try {
$subscription = Get-AzureRmSubscription -SubscriptionName $subscriptionName
}
catch {
Write-Error "Verify that the login credentials are for the administrator and that the specified ARM endpoint: $ArmEndpoint is the valid administrator ARM endpoint for this environment." -ErrorAction Stop
}
$subscription | Select-AzureRmSubscription | Out-Null
$powershellClientId = "0a7bdc5c-7b57-40be-9939-d4c5fc7cd417"
$savedWarningPreference = $WarningPreference
$WarningPreference = 'SilentlyContinue'
$adminToken = Get-AzureStackToken `
-Authority $authority `
-Resource $activeDirectoryServiceEndpointResourceId `
-AadTenantId $tenantID `
-ClientId $powershellClientId `
-Credential $azureStackCredentials
$WarningPreference = $savedWarningPreference
$headers = @{ Authorization = ("Bearer $adminToken") }
return $subscription.SubscriptionId, $headers
}
Export-ModuleMember Get-AzureStackAdminSubTokenHeader
function Get-AADTenantGUID () {
function Get-AzsDirectoryTenantId () {
[CmdletBinding(DefaultParameterSetName = 'AzureActiveDirectory')]
param(
[parameter(mandatory=$true, HelpMessage="AAD Directory Tenant <myaadtenant.onmicrosoft.com>")]
[string] $AADTenantName = "",
[parameter(mandatory=$false, HelpMessage="Azure Cloud")]
[ValidateSet("AzureCloud","AzureChinaCloud","AzureUSGovernment","AzureGermanCloud")]
[string] $AzureCloud = "AzureCloud"
)
$ADauth = (Get-AzureRmEnvironment -Name $AzureCloud).ActiveDirectoryAuthority
$endpt = "{0}{1}/.well-known/openid-configuration" -f $ADauth, $AADTenantName
$OauthMetadata = (Invoke-WebRequest -UseBasicParsing $endpt).Content | ConvertFrom-Json
$AADid = $OauthMetadata.Issuer.Split('/')[3]
$AADid
}
Export-ModuleMember Get-AADTenantGUID
function Get-DirectoryTenantID () {
[CmdletBinding(DefaultParameterSetName='AzureActiveDirectory')]
param(
[Parameter(Mandatory=$true, ParameterSetName='ADFS')]
[Parameter(Mandatory = $true, ParameterSetName = 'ADFS')]
[switch] $ADFS,
[parameter(mandatory=$true,ParameterSetName='AzureActiveDirectory', HelpMessage="AAD Directory Tenant <myaadtenant.onmicrosoft.com>")]
[string] $AADTenantName = "",
[parameter(mandatory = $true, ParameterSetName = 'AzureActiveDirectory', HelpMessage = "AAD Directory Tenant <myaadtenant.onmicrosoft.com>")]
[string] $AADTenantName,
[Parameter(Mandatory=$true, ParameterSetName='ADFS')]
[Parameter(Mandatory=$true, ParameterSetName='AzureActiveDirectory')]
[Parameter(Mandatory = $true, ParameterSetName = 'ADFS')]
[Parameter(Mandatory = $true, ParameterSetName = 'AzureActiveDirectory')]
[string] $EnvironmentName
)
$ADauth = (Get-AzureRmEnvironment -Name $EnvironmentName).ActiveDirectoryAuthority
if($ADFS -eq $true){
if(-not (Get-AzureRmEnvironment -Name $EnvironmentName).EnableAdfsAuthentication){
if ($ADFS -eq $true) {
if (-not (Get-AzureRmEnvironment -Name $EnvironmentName).EnableAdfsAuthentication) {
Write-Error "This environment is not configured to do ADFS authentication." -ErrorAction Stop
}
return $(Invoke-RestMethod $("{0}/.well-known/openid-configuration" -f $ADauth.TrimEnd('/'))).issuer.TrimEnd('/').Split('/')[-1]
}else{
}
else {
$endpt = "{0}{1}/.well-known/openid-configuration" -f $ADauth, $AADTenantName
$OauthMetadata = (Invoke-WebRequest -UseBasicParsing $endpt).Content | ConvertFrom-Json
$AADid = $OauthMetadata.Issuer.Split('/')[3]
@ -399,4 +146,4 @@ function Get-DirectoryTenantID () {
}
}
Export-ModuleMember Get-DirectoryTenantID
Export-ModuleMember Get-AzsDirectoryTenantId

Двоичные данные
Connect/EnvironmentAdd.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.8 MiB

Просмотреть файл

@ -1,12 +1,14 @@
# Connection Scripts
As a prerequisite, make sure that you installed the correct PowerShell modules and versions:
```powershell
Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.9 -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.10 -Scope CurrentUser
```
This tool set allows you to connect to an Azure Stack PoC (Proof of Concept) instance from an external personal laptop. You can then access the portal or log into that environment via PowerShell.
This tool set allows you to connect to an Azure Stack Development Kit (ASDK) instance from an external personal laptop. You can then access the portal or log into that environment via PowerShell.
Instructions below are relative to the .\Connect folder of the [AzureStack-Tools repo](..).
@ -14,27 +16,25 @@ Instructions below are relative to the .\Connect folder of the [AzureStack-Tools
Import-Module .\AzureStack.Connect.psm1
```
# VPN to Azure Stack Proof of Concept
## VPN to Azure Stack Development Kit
The [Connect to Azure Stack](https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-connect-azure-stack) document describes ways to connect to your Azure Stack Proof of Concept environment.
![VPN to Azure Stack Development Kit](/Connect/VPNConnection.gif)
One method is to establish a split tunnel VPN connection to an Azure Stack PoC.
This allows your client computer to become part of the Azure Stack PoC network system and therefore resolve Azure Stack endpoints.
The [Connect to Azure Stack](https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-connect-azure-stack) document describes ways to connect to your Azure Stack Development Kit environment.
The tool will also download root certificate of the targeted Azure Stack PoC instance locally to your client computer.
One method is to establish a split tunnel VPN connection to an Azure Stack Development Kit.
This allows your client computer to become part of the Azure Stack Development Kit network system and therefore resolve Azure Stack endpoints.
The tool will also download the root certificate of the targeted Azure Stack Development Kit instance locally to your client computer.
This will ensure that SSL sites of the target Azure Stack installation are trusted by your client when accessed from the browser or from the command-line tools.
To connect to Azure Stack PoC via VPN, first locate the external BGP-NAT01 address of the target installation.
If you specified a static IP for the BGP-NAT during deployment of the Azure Stack PoC, then use it in the connection example below.
To connect to an Azure Stack Development Kit via VPN, you will need to know the host IP address of the target installation.
If you did not specify a static IP then the BGP-NAT was configured with DHCP. In that case, **read the below section** to obtain your BGP-NAT VM IP by using the IP address of the Azure Stack PoC host (which should be known to you after deployment).
The commands below need to access the Azure Stack PoC host computer and Azure Stack CA, so they need to be trusted hosts in PowerShell. Run PowerShell as administrator and modify TrustedHosts as follows.
The commands below need to access the Azure Stack Development Kit host computer, so it needs to be a trusted host in PowerShell. Run PowerShell as administrator and modify TrustedHosts as follows.
```powershell
# Add Azure Stack PoC host to the trusted hosts on your client computer
Set-Item wsman:\localhost\Client\TrustedHosts -Value "<Azure Stack host address>" -Concatenate
Set-Item wsman:\localhost\Client\TrustedHosts -Value mas-ca01.azurestack.local -Concatenate
# Add Azure Stack Development Kit host to the trusted hosts on your client computer
Set-Item wsman:\localhost\Client\TrustedHosts -Value "<Azure Stack host IP address>" -Concatenate
```
For the VPN connection, use the admin password provided at the time of the Azure Stack deployment.
@ -47,51 +47,43 @@ Then connect your client computer to the environment as follows.
```powershell
# Create VPN connection entry for the current user
Add-AzureStackVpnConnection -ServerAddress <NAT IP> -Password $Password
Add-AzsVpnConnection -ServerAddress <Host IP Address> -Password $Password
# Connect to the Azure Stack instance. This command can be used multiple times.
Connect-AzureStackVpn -Password $Password
Connect-AzsVpn -Password $Password
```
## Obtain the NAT IP address with the Azure Stack PoC host address
This command is helpful if you do not immediately know the NAT IP of the Azure Stack PoC you are trying to connect to. You must know the host address of your Azure Stack PoC.
```powershell
$natIp = Get-AzureStackNatServerAddress -HostComputer "<Azure Stack host address>" -Password $Password
```
## Configure Azure Stack PowerShell Environment
![Adding Azure Stack Environment](/Connect/EnvironmentAdd.gif)
# Configure Azure Stack PowerShell Environment
One method of deploying templates and interacting with your Azure Stack PoC is to access it via PowerShell.
One method of deploying templates and interacting with your Azure Stack Development Kit is to access it via PowerShell.
See the [Azure Stack Install PowerShell](https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-connect-powershell) article to download and install the correct PowerShell modules for Azure Stack.
AzureRM cmdlets can be targeted at multiple Azure clouds such as Azure China, Government, and Azure Stack.
To target your Azure Stack instance as a tenant, an AzureRM environment needs to be registered as follows. The ARM endpoint below is the tenant default for a one-node environment. AzureRM cmdlets can be targeted at multiple Azure clouds such as Azure China, Government, and Azure Stack.
To target your Azure Stack instance as a tenant, an AzureRM environment needs to be registered as follows. The ARM endpoint below is the tenant default for a one-node environment.
```powershell
Add-AzureStackAzureRmEnvironment -Name AzureStack -ArmEndpoint "https://management.local.azurestack.external"
Add-AzureRMEnvironment -Name AzureStack -ArmEndpoint "https://management.local.azurestack.external"
```
To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
```powershell
Add-AzureStackAzureRmEnvironment -Name AzureStackAdmin -ArmEndpoint "https://adminmanagement.local.azurestack.external"
Add-AzureRMEnvironment -Name AzureStackAdmin -ArmEndpoint "https://adminmanagement.local.azurestack.external"
```
Connecting to your environment requires that you obtain the value of your Directory Tenant ID. For **Azure Active Directory** environments provide your directory tenant name:
```powershell
$TenantID = Get-DirectoryTenantID -AADTenantName "<mydirectorytenant>.onmicrosoft.com" -EnvironmentName AzureStackAdmin
$TenantID = Get-AzsDirectoryTenantId -AADTenantName "<mydirectorytenant>.onmicrosoft.com" -EnvironmentName AzureStackAdmin
```
For **ADFS** environments use the following:
```powershell
$TenantID = Get-DirectoryTenantID -ADFS -EnvironmentName AzureStackAdmin
$TenantID = Get-AzsDirectoryTenantId -ADFS -EnvironmentName AzureStackAdmin
```
After registering the AzureRM environment, cmdlets can be easily targeted at your Azure Stack instance. For example:
@ -105,25 +97,3 @@ Similarly, for targeting the administrator endpoints:
```powershell
Login-AzureRmAccount -EnvironmentName "AzureStackAdmin" -TenantId $TenantID
```
## Register Azure RM Providers on new subscriptions
If you are intending to use newly created subscriptions via PowerShell, CLI or direct API calls before deploying any templates or using the Portal, you need to ensure that resource providers are registered on the subscription.
To register providers on the current subscription, do the following.
```powershell
Register-AllAzureRmProviders
```
To register all resource providers on all your subscriptions after logging in using Add-AzureRmAccount do the following. Note that this can take a while.
```powershell
Register-AllAzureRmProvidersOnAllSubscriptions
```
These registrations are idempotent and can be run multiple times. If provider has already been registered, it will simply be reported in the output.

Просмотреть файл

@ -12,39 +12,19 @@ Describe $script:ModuleName {
Get-Module -Name $script:ModuleName |
Should Not Be $null
}
It 'Register-AllAzureRmProvidersOnAllSubscriptions should be exported' {
Get-Command -Name Register-AllAzureRmProvidersOnAllSubscriptions -ErrorAction SilentlyContinue |
Should Not Be $null
}
It 'Register-AllAzureRmProviders should be exported' {
Get-Command -Name Register-AllAzureRmProviders -ErrorAction SilentlyContinue |
Should Not Be $null
}
It 'Get-AzureStackAadTenant should be exported' {
Get-Command -Name Get-AzureStackAadTenant -ErrorAction SilentlyContinue |
Should Not Be $null
}
It 'Add-AzureStackAzureRmEnvironment should be exported' {
Get-Command -Name Add-AzureStackAzureRmEnvironment -ErrorAction SilentlyContinue |
It 'Add-AzsEnvironment should be exported' {
Get-Command -Name Add-AzsEnvironment -ErrorAction SilentlyContinue |
Should Not Be $null
}
It 'Get-AzureStackNatServerAddress should be exported' {
Get-Command -Name Get-AzureStackNatServerAddress -ErrorAction SilentlyContinue |
It 'Add-AzsVpnConnection should be exported' {
Get-Command -Name Add-AzsVpnConnection -ErrorAction SilentlyContinue |
Should Not Be $null
}
It 'Add-AzureStackVpnConnection should be exported' {
Get-Command -Name Add-AzureStackVpnConnection -ErrorAction SilentlyContinue |
Should Not Be $null
}
It 'Connect-AzureStackVpn should be exported' {
Get-Command -Name Connect-AzureStackVpn -ErrorAction SilentlyContinue |
It 'Connect-AzsVpn should be exported' {
Get-Command -Name Connect-AzsVpn -ErrorAction SilentlyContinue |
Should Not Be $null
}
}
@ -68,36 +48,25 @@ InModuleScope $script:ModuleName {
$EnvironmentName = $global:EnvironmentName
Set-Item wsman:\localhost\Client\TrustedHosts -Value $HostComputer -Concatenate
Set-Item wsman:\localhost\Client\TrustedHosts -Value mas-ca01.azurestack.local -Concatenate
Set-Item wsman:\localhost\Client\TrustedHosts -Value Azs-ca01.azurestack.local -Concatenate
Describe 'ConnectModule - Accessing Environment Data' {
It 'Recovered AAD Tenant ID should be correct' {
$global:AadTenantID = Get-AzureStackAadTenant -HostComputer $HostComputer -User $AdminUser -Password $AdminPassword
Write-Verbose "Aad Tenant ID is $global:AadTenantID" -Verbose
$global:AadTenantID | Should Not Be $null
}
It 'Get-AzureStackNatServerAddress should return valid NAT address' {
$script:NatIPAddress = Get-AzureStackNatServerAddress -natServer $natServer -HostComputer $HostComputer -User $AdminUser -Password $AdminPassword
Write-Verbose "Returned NAT IP Address of $natIPAddress" -Verbose
[IPAddress]$script:NatIPAddress | Should Not Be $null
}
It 'Add-AzureStackVpnConnection should correctly return a VPN connection to a One Node' {
Add-AzureStackVpnConnection -ServerAddress $script:NatIPAddress -ConnectionName $VPNConnectionName -Password $AdminPassword
It 'Add-AzsVpnConnection should correctly return a VPN connection to a One Node' {
Add-AzsVpnConnection -ServerAddress $script:NatIPAddress -ConnectionName $VPNConnectionName -Password $AdminPassword
Get-VpnConnection -Name $VPNConnectionName | Should Not Be $null
}
It 'Connect-AzureStackVpn should successfully connect to a One Node environment' {
{Connect-AzureStackVpn -ConnectionName $VPNConnectionName -User $AdminUser -Password $AdminPassword} | Should Not Throw
It 'Connect-AzsVpn should successfully connect to a One Node environment' {
{Connect-AzsVpn -ConnectionName $VPNConnectionName -User $AdminUser -Password $AdminPassword} | Should Not Throw
}
It 'Add-AzureStackAzureRmEnvironment should successfully add a an administrator environment' {
Add-AzureStackAzureRmEnvironment -ArmEndpoint $armEndpoint -Name $EnvironmentName
It 'Add-AzsEnvironment should successfully add a an administrator environment' {
Add-AzsEnvironment -ArmEndpoint $armEndpoint -Name $EnvironmentName
Get-AzureRmEnvironment -Name $EnvironmentName | Should Not Be $null
}
It 'User should be able to login to environment successfully created by Add-AzureStackAzureRmEnvironment' {
It 'User should be able to login to environment successfully created by Add-AzsEnvironment' {
Write-Verbose "Aad Tenant ID is $global:AadTenantID" -Verbose
Write-Verbose "Passing credential to Login-AzureRmAccount" -Verbose
{Login-AzureRmAccount -EnvironmentName $EnvironmentName -TenantId $global:AadTenantID -Credential $global:AzureStackLoginCredentials} | Should Not Throw
@ -107,25 +76,25 @@ InModuleScope $script:ModuleName {
Get-AzureRmResourceGroup | Should Not Be $null
}
It 'Get-AzureStackAdminSubTokenHeader should retrieve a valid admin token' {
$subID, $headers = Get-AzureStackAdminSubTokenHeader -TenantID $global:AadTenantID -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds
It 'Get-AzsAdminSubTokenheader should retrieve a valid admin token' {
$subID, $headers = Get-AzsAdminSubTokenheader -TenantID $global:AadTenantID -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds
Write-Verbose "Admin subscription ID was $subID" -Verbose
Write-Verbose "Acquired token was $headers.Authorization" -Verbose
$headers.Authorization | Should Not Be $null
$subID | Should Not Be $null
}
It 'Register-AllAzureRmProviders should register all resource providers for the current subscription' {
Register-AllAzureRmProviders
It 'Register-AzsProvider should register all resource providers for the current subscription' {
Register-AzsProvider
$unRegisteredProviders = Get-AzureRmResourceProvider | Where-Object {$_.RegistrationState -ne "Registered"}
$unRegisteredProviders | Should Be $null
}
It 'Register-AllAzureRmProvidersOnAllSubscriptions should register all resource providers for all subscriptions' {
Register-AllAzureRmProvidersOnAllSubscriptions
It 'Register-AzsProviderOnAllSubscriptions should register all resource providers for all subscriptions' {
Register-AzsProviderOnAllSubscriptions
$unRegisteredProviders = Get-AzureRmResourceProvider | Where-Object {$_.RegistrationState -ne "Registered"}
$unRegisteredProviders | Should Be $null
}
}
}
}

Двоичные данные
Connect/VPNConnection.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.7 MiB

Просмотреть файл

@ -1,71 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# See LICENSE.txt in the project root for license information.
<# 
 
.SYNOPSIS 
 
Modify the boot entry and reboot the Azure Stack host back to the base Operating System, so that Azure Stack can be redeployed. 
 
.DESCRIPTION 
 
BootMenuNoKVM updates the boot configuration with the original entry, and then prompts to reboot the host.
Because the default boot entry is set with this script, no KVM or manual selection of the boot entry is required as the machine restarts.
.EXAMPLE 
Prompt user for the desired boot configuraiton and confirm reboot of the host so a redeployment of Azure Stack can begin.
This does not require KVM access to the host for selection of the correct Operating System as the machine restarts.
.\BootMenuNoKVM.ps1
.NOTES 
 
You will need execute this script in an elevated PS console session.
 
#>
#requires -version 4.0
#requires runasadministrator
#region Menu
$prompt = ('Are you sure you want to configure this onetime boot value and reboot now?' + $title)
$Yes = New-Object System.Management.Automation.Host.ChoiceDescription '&Yes','Reboot now'
$Abort = New-Object System.Management.Automation.Host.ChoiceDescription '&Abort','Abort'
$options = [System.Management.Automation.Host.ChoiceDescription[]] ($Yes,$Abort)
#endregion
$bootOptions = bcdedit /enum | Select-String 'path' -Context 2,1
cls
#region Selection
write-host 'This script specifies a one-time display order to be used for the next boot. Afterwards, the computer reverts to the original display order.' -ForegroundColor Yellow
write-host 'Select the Operating System to boot from:' -ForegroundColor Cyan
$menu = @{}
for ($i=1;$i -le $bootOptions.count; $i++) {
Write-Host "$i. $($bootOptions[$i-1].Context.PostContext[0] -replace '^description +')"
$menu.Add($i,($bootOptions[$i-1].Context.PreContext[0]))
}
[int]$ans = Read-Host 'Enter selection'
$selection = $menu.Item($ans)
#endregion
$BootEntry = $selection -replace '^identifier +'
if($Selection -ne $null)
{
$choice = $host.ui.PromptForChoice($title,$prompt,$options,0)
if ($choice -eq 0)
{
$BootID = '"' + $BootEntry + '"'
bcdedit /bootsequence $BootID
Restart-Computer
}
else
{
write-host 'No changes are made to the boot configuration. Exiting..' -ForegroundColor Yellow
Break
}
}
else
{write-host 'Not a valid selection. No changes are made to the boot configuration. Exiting..' -ForegroundColor Yellow}

Двоичные данные
Deployment/Deployment.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.0 MiB

Просмотреть файл

@ -1,220 +0,0 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# See LICENSE.txt in the project root for license information.
<# 
 
.SYNOPSIS 
 
Prepare the host to boot from the Azure Stack virtual harddisk. 
 
.DESCRIPTION 
 
PrepareBootFromVHD updates the boot configuration with an Azure Stack entry.
It will verify if the disk that hosts the CloudBuilder.vhdx contains the required free disk space, Optionally copy drivers and an unattend.xml that does not require KVM access.
 
.PARAMETER CloudBuilderDiskPath  
 
Path to the CloudBuilder.vhdx. This parameter is mandatory.
.PARAMETER DriverPath  
 
This optional parameter allows you to add additional drivers for the host in the virtual harddisk. Specify the path that contains the drivers and all its content wil be copied the to CloudBuilder.vhdx.
 
.PARAMETER ApplyUnattend 
 
ApplyUnattend is a switch parameter. If this parameter is specified, the configuration of the Operating System is automated.
After the host reboots to the CloudBuilder.vhdx, the Operating System is automatically configured and you can connect to the host with RDP without KVM requirement.
If this parameter is specified, you will be prompted for an local administrator password that is used for the unattend.xml.
If this parameter is not specified, a minimal unattend.xml is used to enable Remote Desktop. KVM is required to configure the Operating System when booting from vs.vhdx for the first time.
.PARAMETER AdminPassword  
 
The AdminPassword parameter is only used when the ApplyUnnatend parameter is set. The Password requires minimal 6 characters.
 
.EXAMPLE 
 
Prepare the host to boot from CloudBuilder.vhdx. This requires KVM access to the host for configuring the Operating System.
.\PrepareBootFromVHD.ps1 -CloudBuilderPath c:\CloudBuilder.vhdx -DriverPath c:\VhdDrivers
 
.EXAMPLE  
 
Prepare the host to boot from CloudBuilder.vhdx. The Operating System is automatically configured with an unattend.xml.
.\PrepareBootFromVHD.ps1 -CloudBuilderPath c:\CloudBuilder.vhdx -ApplyUnattend
  
.NOTES 
 
You will need at least (120GB - Size of the CloudBuilder.vhdx file) of free disk space on the disk that contains the CloudBuilder.vhdx.
 
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true)]
[String]$CloudBuilderDiskPath,
[Parameter(Mandatory=$false)]
[string[]]$DriverPath = $null,
[Parameter(Mandatory = $false)]
[switch]$ApplyUnattend,
[Parameter(Mandatory = $false)]
[String]$AdminPassword,
[Parameter(Mandatory = $false)]
[String]$VHDLanguage = "en-US"
)
$error.Clear()
#region Allow for manual override of PS (replace $PSScriptRoot with a path)
$currentPath = $PSScriptRoot
# $currentPath = 'C:\ForRTMBuilds'
# $CloudBuilderDiskPath = 'C:\CloudBuilder.vhdx'
#endregion
#region Check parameters and prerequisites
if (-not (Test-Path -Path $CloudBuilderDiskPath)) {
Write-Host "Can't find CloudBuilder.vhdx." -ForegroundColor Red
Exit
}
if ((Get-DiskImage -ImagePath $CloudBuilderDiskPath).Attached) {
Write-Host "CloudBuilder.vhdx is already mounted." -ForegroundColor Red
Exit
}
# Validate the CloudBuilder.vhdx is in a physical disk
$cbhDriveLetter = (Get-Item $CloudBuilderDiskPath).PSDrive.Name
if (-not $cbhDriveLetter) {
Write-Host "The given CloudBuilder.vhdx path is not a local path." -ForegroundColor Red
Exit
}
else {
$hostDisk = Get-Partition -DriveLetter $cbhDriveLetter | Get-Disk
if ($hostDisk.Model -match 'Virtual Disk') {
Write-Host "The CloudBuilder.vhdx is in a virtual hard disk, please place it in a physical disk." -ForegroundColor Red
Exit
}
}
if ($ApplyUnattend) {
# Check if unattend_NoKVM.xml is downloaded
$unattendRawFile = Join-Path $currentPath 'unattend_NoKVM.xml'
if (-not (Test-Path $unattendRawFile)) {
Write-Host "-ApplyUnattend is specified, but unattend_NoKVM.xml is not downloaded to the same directory of this script." -ForegroundColor Red
Exit
}
# Check Admin password for unattend
if(-not $AdminPassword) {
while ($SecureAdminPassword.Length -le 6) {
[System.Security.SecureString]$SecureAdminPassword = read-host 'Password for the local administrator account of the Azure Stack host. Requires 6 characters minimum' -AsSecureString
}
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureAdminPassword)
$AdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
Write-Host "The following password will be configured for the local administrator account of the Azure Stack host:"
Write-Host $AdminPassword -ForegroundColor Cyan
}
}
# Validate disk space for expanding cloudbuilder.vhdx
$cbhDiskSize = [math]::truncate((get-volume -DriveLetter $cbhDriveLetter).Size / 1GB)
$cbhDiskRemaining = [math]::truncate((get-volume -DriveLetter $cbhDriveLetter).SizeRemaining / 1GB)
$cbDiskSize = [math]::truncate((Get-Item $CloudBuilderDiskPath).Length / 1GB)
$cbDiskSizeReq = 120
if (($cbDiskSizeReq - $cbDiskSize) -ge $cbhDiskRemaining) {
Write-Host 'Error: Insufficient disk space' -BackgroundColor Red
Write-Host 'Cloudbuilder.vhdx is placed on' ((Get-Item $CloudBuilderDiskPath).PSDrive.Root) -ForegroundColor Yellow
Write-Host 'When you boot from CloudBuilder.vhdx the virtual hard disk will be expanded to its full size of' $cbDiskSizeReq 'GB.' -ForegroundColor Yellow
Write-Host ((Get-Item $CloudBuilderDiskPath).PSDrive.Root) 'does not contain enough free space.' -ForegroundColor Yellow
Write-Host 'You need' ($cbDiskSizeReq - $cbDiskSize) 'GB of free disk space for a succesfull boot from CloudBuilder.vhdx, but' ((Get-Item $CloudBuilderDiskPath).PSDrive.Root) 'only has' $cbhDiskRemaining 'GB remaining.' -ForegroundColor Yellow
Write-Host 'Ensure Cloudbuilder.vhdx is placed on a local disk that contains enough free space and rerun this script.' -ForegroundColor Yellow
Write-Host 'Exiting..' -ForegroundColor Yellow
Exit
}
#endregion
#region Prepare Azure Stack virtual harddisk
Write-Host "Preparing Azure Stack virtual harddisk"
$cbdisk = Mount-DiskImage -ImagePath $CloudBuilderDiskPath -PassThru | Get-DiskImage | Get-Disk
$partitions = $cbdisk | Get-Partition | Sort-Object -Descending -Property Size
$CBDriveLetter = $partitions[0].DriveLetter
# ApplyUnattend
if($ApplyUnattend) {
Write-Host "Apply unattend.xml with given password and language" -ForegroundColor Cyan
$UnattendedFile = Get-Content ($currentPath + '\unattend_NoKVM.xml')
$UnattendedFile = ($UnattendedFile).Replace('%productkey%', '74YFP-3QFB3-KQT8W-PMXWJ-7M648')
$UnattendedFile = ($UnattendedFile).Replace('%locale%', $VHDLanguage)
$UnattendedFile = ($UnattendedFile).Replace('%adminpassword%', $AdminPassword)
$UnattendedFile | Out-File ($CBDriveLetter+":\unattend.xml") -Encoding ascii
}
else {
# Apply defautl unattend.xml if it exists
$defaultUnattend = Join-Path $currentPath 'Unattend.xml'
if (Test-Path $defaultUnattend) {
Write-Host "Apply default unattend.xml to disable IE-ESC and enable remote desktop" -ForegroundColor Cyan
Copy-Item $defaultUnattend -Destination ($CBDriveLetter + ':\') -Force
}
}
# Add drivers
if (-not $DriverPath) {
Write-Host "Apply given drivers" -ForegroundColor Cyan
foreach ($subdirectory in $DriverPath) {
Add-WindowsDriver -Driver $subdirectory -Path "$($CBDriveLetter):\" -Recurse
}
}
#endregion
#region Configure boot options
# Remove boot from previous deployment
$bootOptions = bcdedit /enum | Select-String 'path' -Context 2,1
$bootOptions | ForEach {
if ((($_.Context.PreContext[1] -replace '^device +') -like '*CloudBuilder.vhdx*') `
-and ((($_.Context.PostContext[0] -replace '^description +') -eq 'AzureStack TP2') `
-or (($_.Context.PostContext[0] -replace '^description +') -eq 'Azure Stack'))) {
Write-Host 'The boot configuration contains an existing CloudBuilder.vhdx entry' -ForegroundColor Cyan
Write-Host 'Description:' ($_.Context.PostContext[0] -replace '^description +') -ForegroundColor Cyan
Write-Host 'Device:' ($_.Context.PreContext[1] -replace '^device +') -ForegroundColor Cyan
Write-Host 'Removing the old entry'
$BootID = '"' + ($_.Context.PreContext[0] -replace '^identifier +') + '"'
Write-Host 'bcdedit /delete' $BootID -ForegroundColor Yellow
bcdedit /delete $BootID
}
}
# Add boot entry for CloudBuilder.vhdx
Write-Host 'Creating new boot entry for CloudBuilder.vhdx' -ForegroundColor Cyan
Write-Host 'Running command: bcdboot' $CBDriveLetter':\Windows' -ForegroundColor Yellow
bcdboot $CBDriveLetter':\Windows'
$bootOptions = bcdedit /enum | Select-String 'path' -Context 2,1
$bootOptions | ForEach {
if ((($_.Context.PreContext[1] -replace '^device +') -eq ('partition='+$CBDriveLetter+':') `
-or (($_.Context.PreContext[1] -replace '^device +') -like '*CloudBuilder.vhdx*')) `
-and (($_.Context.PostContext[0] -replace '^description +') -ne 'Azure Stack')) {
Write-Host 'Updating description for the boot entry' -ForegroundColor Cyan
Write-Host 'Description:' ($_.Context.PostContext[0] -replace '^description +') -ForegroundColor Cyan
Write-Host 'Device:' ($_.Context.PreContext[1] -replace '^device +') -ForegroundColor Cyan
$BootID = '"' + ($_.Context.PreContext[0] -replace '^identifier +') + '"'
Write-Host 'bcdedit /set' $BootID 'description "Azure Stack"' -ForegroundColor Yellow
bcdedit /set $BootID description "Azure Stack"
}
}
#endregion
if(-not $error) {
Write-Host "Restart computer to boot from Azure Stack virtual harddisk" -ForegroundColor Cyan
### Restart Computer ###
Restart-Computer -Confirm
}
else {
Write-Host "Fail to prepare CloudBuilder.vhdx. Errors: $($error)" -ForegroundColor Red
}

Просмотреть файл

@ -1,90 +1,91 @@
# Deployment of Azure Stack
# Azure Stack Development Kit installer
Instructions below are relative to the .\Deployment folder of the [AzureStack-Tools repo](..).
The Azure Stack Development Kit installer provides a UI with the following features
## Azure Stack TP3 Support Files
- Prepare the SafeOS for deployment
- Prepare the Azure Stack Development Kit Installation
- Rerun and Gather Logs
- Reboot to SafeOS
To easily download the Azure Stack TP3 support files from this repository, run the following PowerShell script from your POC machine:
To install the Azure Stack Development Kit you require
- A physical server that meets the requirements
- The latest cloudbuilder.vhdx
- The asdk-installer.ps1 script
## Download the Azure Stack Development Kit installer
To easily download the Azure Stack Development Kit installer from this repository, run the following PowerShell script from your SafeOS host:
```powershell
# Variables
$Uri = 'https://raw.githubusercontent.com/Azure/AzureStack-Tools/master/Deployment/'
$LocalPath = 'c:\AzureStack_TP3_SupportFiles'
$Uri = 'https://raw.githubusercontent.com/Azure/AzureStack-Tools/master/Deployment/asdk-installer.ps1'
$LocalPath = 'c:\AzureStack_Installer'
# Create folder
New-Item $LocalPath -Type directory
# Download files
'BootMenuNoKVM.ps1', 'PrepareBootFromVHD.ps1', 'Unattend.xml', 'unattend_NoKVM.xml' | foreach { Invoke-WebRequest ($uri + $_) -OutFile ($LocalPath + '\' + $_) }
# Download file
Invoke-WebRequest $uri -OutFile ($LocalPath + '\' + 'asdk-installer.ps1')
```
## Prepare to Deploy (boot from VHD)
## Prepare the SafeOS for deployment
This tool allows you to easily prepare your Azure Stack Technical Preview deployment, by preparing the host to boot from the provided Azure Stack Technical Preview virtual harddisk (CloudBuilder.vhdx).
The installer script can be used to prepare your host for the deployment of the Azure Stack Development Kit. After you have downloaded the cloudbuilder.vhdx, run the script on the server you would like to deploy to.
PrepareBootFromVHD updates the boot configuration with an **Azure Stack** entry.
It will verify if the disk that hosts the CloudBuilder.vhdx contains the required free disk space, and optionally copy drivers and an unattend.xml that does not require KVM access.
Select the cloudbuilder.vhdx and optionally specify a path to a folder containing drivers for the host.
The host can be configured with the following options:
- **Local administrator password** - If you uncheck this option the host will prompt for a password during the oobe setup when rebooting to the cloudbuilder.vhdx. Not specifying a local administrator password requires KVM access to the host to specify the password during boot.
- **Computer name** - You can specify the name for the Azure Stack Development Kit host. The name needs to comply with FQDN requirements and cannot be longer than 15 characters. If you do not select the option, Windows generates a computername during OOBE.
- **Timezone** - This options sets timezone for the Azure Stack Development Kit host to the selected value. If this option is not selected the timezone will be configred to (UTC-8:00) Pacific Time (US & Canada)
- **Static IP Configuration** If the Azure Stack development kit needs to be configured with a static IP address, select this option. The installer will prompt for the networking interface and copy the current values for use in the cloudbuilder.vhdx during reboot. You can override the values that where copied if needed. If you do not select this option the network interfaces will be configured with DHCP when rebooted into the cloudbuilder.vhdx
You will need at least (120GB - Size of the CloudBuilder.vhdx file) of free disk space on the disk that contains the CloudBuilder.vhdx.
A job will perform the following actions:
### PrepareBootFromVHD.ps1 Execution
- Verify if the disk containing the cloudbuilder.vhdx has **enough space** to expand the disk. You will need at least (120GB - Size of the cloudBuilder.vhdx file) of free disk space on the disk that contains the cloudBuilder.vhdx.
- Remove previous **Azure Stack** boot entries .
- **Mount** the cloudbuilder.vhdx.
- Add **bootfiles** to the Operating System disk.
- Updates the boot configuration with an **Azure Stack** entry for the virtual hard disk and sets it to the default value.
- Adds an **unattend** file to the Operating System on the mounted virtual hard disk, based on the selections made in the wizard.
- Adds **drivers** to the operating system, if that option was selected during the wizard.
There are five parameters for this script:
- **CloudBuilderDiskPath** (required) – path to the CloudBuilder.vhdx on the HOST
- **DriverPath** (optional) – allows you to add additional drivers for the host in the virtual HD
- **ApplyUnattend** (optional) – switch parameter, if specified, the configuration of the OS is automated, and the user will be prompted for the AdminPassword to configure at boot (requires provided accompanying file **unattend_NoKVM.xml**)
- If you do not leverage this parameter, the generic **unattend.xml** file is used without further customization
- **AdminPassword** (optional) – only used when the **ApplyUnattend** parameter is set, requires a minimum of 6 characters
- **VHDLanguage** (optional) – specifies the VHD language, defaulted to “en-US”
When the job is completed you finalize the wizard to reboot into the cloudbuilder.vhdx. If you have enabled the local administrator password and have connectivity to the IP address (either the static one specified or based on DHCP), you can remote into the host with RDP after the OOBE completes.
## Prepare the Azure Stack Development Kit installation
Once the host has succesfully completed booting from the cloudbuilder.vhdx, logon to the host as administrator and start the same installation script again. The installer script was originally stored on c:\AzureStack_Installer. After the reboot into cloudbuilder.vhdx the SafeOS system disk is presented as a datadisk in the Operating System of the Azure Stack Development Kit host OS. Browse for the script and execute it by righclicking it and select Run with PowerShell. Or browse to the path in a PowerShell session and run;
```powershell
.\PrepareBootFromVHD.ps1 -CloudBuilderDiskPath C:\CloudBuilder.vhdx -ApplyUnattend
.\asdk-installer.ps1
```
If you execute this exact command, you will be prompted to enter the **AdminPassword** parameter.
Click install to start the deployment wizard. Select the preferred identity provider for your Azure Stack Development Kit deployment.
During execution of this script, you will have visibility to the **bcdedit** command execution and output.
- **Azure Cloud** : Azure Active Directory
- **ADFS** : Local ADFS instance as part of the installation
When the script execution is complete, you will be asked to confirm reboot.
If there are other users logged in, this command will fail, run the following command to continue:
```powershell
Restart-Computer -Force
```
If you selected Azure Cloud, specify the Azure Active Directory tenant (e.g. azurestack.onmicrosoft.com).
### HOST Reboot
Submit the local administrator password. This value submitted has to match the current configured local administrator password.
If you used **ApplyUnattend** and provided an **AdminPassword** during the execution of the PrepareBootFromVHD.ps1 script, you will not need KVM to access the HOST once it completes its reboot cycle.
In the network interface screen, select the adapter that will be used for the Azure Stack Development Kit. Ensure you have access to the IP address as all other adapters will be disabled by the installer.
Of course, you may still need KVM (or some other kind of alternate connection to the HOST other than RDP) if you meet one of the following:
- You chose not to use **ApplyUnattend**
- It will automatically run Windows Setup as the VHD OS is prepared. When asked, provide your country, language, keyboard, and other preferences.
- Something goes wrong in the reboot/customization process, and you are not able to RDP to the HOST after some time.
The network configuration screen allows you to specify the settings for the BGPNAT vm. The default settings uses DHCP for the BGPNAT vm. You can set it to static, but only use this parameter if DHCP cant assign a valid IP address for Azure Stack to access the Internet. A static IP address needs to be specified with the subnetmask length (e.g. 10.0.0.5/24). Optionally you can specify the TimeServer, DNS Server and VLAN ID.
## Prepare to Redeploy (boot back to original/base OS)
The summary screen displays the PowerShell script that will be executed. Click deploy start the deployment of the Azure Stack Development Kit.
This tool allows you to easily initiate a redeployment of your Azure Stack Technical Preview deployment, by presenting you with the boot OS options, and the choice to boot back into the original/base OS (away from the previously created **Azure Stack**).
> Note: When you have selected Azure Cloud as the identity provider, you will be prompted 2 to 3 minutes after the deployment has started. Please ensure you submit your Azure AD credentials.
BootMenuNoKVM updates the boot configuration with the original/base entry, and then prompts to reboot the host.
Because the default boot entry is set with this script, no KVM or manual selection of the boot entry is required as the machine restarts.
## Rerun and gather logs
### BootMenuNoKVM.ps1 Execution
If during the installation an error occures, you can start the installer script to rerun the installation from where it failed. After 3 failed reruns the installer script will gather the logs for support purposes and stores them in c:\AzureStackLogs
There are no parameters for this script, but it must be executed in an elevated PowerShell console.
If the installation completed succesfully, but you ran into an issue that requires you to gather the log files, you can run the same installer script. The installer will present you with the option to gather the logs and store them in c:\AzureStackLogs
```powershell
.\BootMenuNoKVM.ps1
```
## Reboot
During execution of this script, you will be prompted to choose the default OS to boot back into after restart. This will become your new default OS, just like **Azure Stack** became the new default OS during deployment.
The installer script allows you to easily initiate a reboot to the SafeOS to start a redeployment of your Azure Stack Development Kit. Start the installer script and select Reboot. You will be presented with the current boot options. Select the entry for the SafeOS and select Reboot. This creates a onetime override in the boot order. The SafeOS boot entry will be select automatically. The next reboot the boot configuration will resume its normal order and the host will boot into the cloudbuilder.vhdx again.
When the script execution is complete, you will be asked to confirm reboot.
If there are other users logged in, this command will fail, run the following command to continue:
```powershell
Restart-Computer -Force
```
### HOST Reboot
Because you are choosing the new default OS to boot into, you will not need KVM to access the HOST once it completes its reboot cycle. It will boot into the OS you chose during the execution of the script.
Once the HOST is rebooted back to the original/base OS, you will need to DELETE the previous/existing CloudBuilder.vhdx file, and then copy down a new one to begin redeployment.
### Note
The Azure Stack Development Kit installer script is based on PowerShell and the Windows Presentation Foundation. It is published in this public repository so you can make improvements to it by submitting a pull request.

Просмотреть файл

@ -1,25 +0,0 @@
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:ms="urn:schemas-microsoft-com:asm.v3">
<settings pass="specialize">
<component name="Networking-MPSSVC-Svc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<FirewallGroups>
<FirewallGroup wcm:action="add" wcm:keyValue="RemoteDesktop">
<Active>true</Active>
<Profile>all</Profile>
<Group>@FirewallAPI.dll,-28752</Group>
</FirewallGroup>
</FirewallGroups>
</component>
<component name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<IEHardenAdmin>false</IEHardenAdmin>
<IEHardenUser>false</IEHardenUser>
</component>
</settings>
<settings pass="oobeSystem">
<component xmlns="" name="Microsoft-Windows-TerminalServices-LocalSessionManager" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="amd64">
<fDenyTSConnections>false</fDenyTSConnections>
</component>
<component xmlns="" name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="amd64">
<UserAuthentication>0</UserAuthentication>
</component>
</settings>
</unattend>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,76 +0,0 @@
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="windowsPE">
<component name="Microsoft-Windows-Setup" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="AMD64">
<UpgradeData>
<Upgrade>false</Upgrade>
</UpgradeData>
<UserData>
<AcceptEula>true</AcceptEula>
<FullName>Microsoft</FullName>
<Organization>Microsoft</Organization>
<ProductKey>
<WillShowUI>OnError</WillShowUI>
<Key>%productkey%</Key>
</ProductKey>
</UserData>
<Restart>Restart</Restart>
</component>
<component name="Microsoft-Windows-International-Core-WinPE" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="AMD64">
<SetupUILanguage>
<UILanguage>en-us</UILanguage>
<WillShowUI>OnError</WillShowUI>
</SetupUILanguage>
<UILanguage>%locale%</UILanguage>
<SystemLocale>%locale%</SystemLocale>
<UserLocale>%locale%</UserLocale>
<InputLocale>0409:00000409</InputLocale>
</component>
</settings>
<settings pass="specialize">
<component xmlns="" name="Microsoft-Windows-TerminalServices-LocalSessionManager" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="amd64">
<fDenyTSConnections>false</fDenyTSConnections>
</component>
<component xmlns="" name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="amd64">
<UserAuthentication>0</UserAuthentication>
</component>
<component name="Microsoft-Windows-Shell-Setup" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="AMD64">
<ComputerName></ComputerName>
</component>
<component name="Networking-MPSSVC-Svc" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<FirewallGroups>
<FirewallGroup wcm:action="add" wcm:keyValue="RemoteDesktop">
<Active>true</Active>
<Profile>all</Profile>
<Group>@FirewallAPI.dll,-28752</Group>
</FirewallGroup>
</FirewallGroups>
</component>
<component name="Microsoft-Windows-IE-ESC" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<IEHardenAdmin>false</IEHardenAdmin>
<IEHardenUser>false</IEHardenUser>
</component>
<component name="Microsoft-Windows-Deployment" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="AMD64">
<RunSynchronous>
<RunSynchronousCommand>
<Order>1</Order>
<Path>cmd /c net user administrator /active:yes</Path>
<Description>RS1</Description>
<WillReboot>Never</WillReboot>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-Shell-Setup" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" processorArchitecture="AMD64">
<UserAccounts>
<AdministratorPassword>
<Value>%adminpassword%</Value>
<PlainText>true</PlainText>
</AdministratorPassword>
</UserAccounts>
<OOBE>
<SkipMachineOOBE>true</SkipMachineOOBE>
</OOBE>
</component>
</settings>
</unattend>

Просмотреть файл

@ -8,11 +8,12 @@
This function fetches the OpenID configuration metadata from the identity system and parses the Directory TenantID out of it.
Azure Stack AD FS is configured to be a single tenanted identity system with a TenantID.
.EXAMPLE
Get-DirectoryTenantIdentifier -authority https://login.windows.net/microsoft.onmicrosoft.com
Get-AzsDirectoryTenantIdentifier -authority https://login.windows.net/microsoft.onmicrosoft.com
.EXAMPLE
Get-DirectoryTenantIdentifier -authority https://adfs.local.azurestack.external/adfs
Get-AzsDirectoryTenantIdentifier -authority https://adfs.local.azurestack.external/adfs
#>
function Get-DirectoryTenantIdentifier {
function Get-AzsDirectoryTenantidentifier {
[CmdletBinding()]
Param
(
@ -25,17 +26,20 @@ function Get-DirectoryTenantIdentifier {
return $(Invoke-RestMethod $("{0}/.well-known/openid-configuration" -f $authority.TrimEnd('/'))).issuer.TrimEnd('/').Split('/')[-1]
}
Export-ModuleMember -Function 'Get-AzsDirectoryTenantidentifier'
<#
.Synopsis
This function is used to create a Service Principal on teh AD Graph
.DESCRIPTION
The command creates a certificate in the cert store of the local user and uses that certificate to create a Service Principal in the Azure Stack Stamp Active Directory.
.EXAMPLE
$servicePrincipal = New-ADGraphServicePrincipal -DisplayName "mySPApp" -AdminCredential $(Get-Credential) -Verbose
$servicePrincipal = New-AzsAdGraphServicePrincipal -DisplayName "mySPApp" -AdminCredential $(Get-Credential) -Verbose
.EXAMPLE
$servicePrincipal = New-ADGraphServicePrincipal -DisplayName "mySPApp" -AdminCredential $(Get-Credential) -DeleteAndCreateNew -Verbose
$servicePrincipal = New-AzsAdGraphServicePrincipal -DisplayName "mySPApp" -AdminCredential $(Get-Credential) -DeleteAndCreateNew -Verbose
#>
function New-ADGraphServicePrincipal {
function New-AzsAdGraphServicePrincipal {
[CmdletBinding()]
Param
(
@ -46,9 +50,9 @@ function New-ADGraphServicePrincipal {
$DisplayName,
# Adfs Machine name
[Parameter(Mandatory = $true , Position = 1)]
[Parameter(Mandatory = $true, Position = 1)]
[string]
$AdfsMachineName = "mas-adfs01.azurestack.local",
$AdfsMachineName,
# Domain Administrator Credential to create Service Principal
[Parameter(Mandatory = $true,
@ -91,13 +95,13 @@ function New-ADGraphServicePrincipal {
Write-Verbose -Message "Creating new application group with name '$applicationGroupName'."
$applicationParameters = @{
Name = $applicationGroupName
Description = $applicationGroupDescription
ClientType = 'Confidential'
ClientId = $shellSiteApplicationId
ClientDisplayName = $shellSiteDisplayName
Name = $applicationGroupName
Description = $applicationGroupDescription
ClientType = 'Confidential'
ClientId = $shellSiteApplicationId
ClientDisplayName = $shellSiteDisplayName
ClientRedirectUris = $shellSiteRedirectUri
ClientDescription = $shellSiteClientDescription
ClientDescription = $shellSiteClientDescription
ClientCertificates = $ClientCertificate
}
$defaultTimeOut = New-TimeSpan -Minutes 10
@ -105,9 +109,9 @@ function New-ADGraphServicePrincipal {
Write-Verbose -Message "Shell Site ApplicationGroup: $($applicationGroup | ConvertTo-Json)"
return [pscustomobject]@{
ObjectId = $applicationGroup.Identifier
ObjectId = $applicationGroup.Identifier
ApplicationId = $applicationParameters.ClientId
Thumbprint = $ClientCertificate.Thumbprint
Thumbprint = $ClientCertificate.Thumbprint
}
}
$domainAdminSession = New-PSSession -ComputerName $AdfsMachineName -Credential $AdminCredential -Authentication Credssp -Verbose
@ -126,14 +130,14 @@ function Initialize-AzureRmEnvironment([string]$EnvironmentName, [string] $Resou
$directoryTenantId = (New-Object uri(Invoke-RestMethod "$($endpoints.authentication.loginEndpoint.TrimEnd('/'))/$DirectoryTenantName/.well-known/openid-configuration").token_endpoint).AbsolutePath.Split('/')[1]
$azureEnvironmentParams = @{
Name = $EnvironmentName
ActiveDirectoryEndpoint = $endpoints.authentication.loginEndpoint.TrimEnd('/') + "/"
Name = $EnvironmentName
ActiveDirectoryEndpoint = $endpoints.authentication.loginEndpoint.TrimEnd('/') + "/"
ActiveDirectoryServiceEndpointResourceId = $endpoints.authentication.audiences[0]
AdTenant = $directoryTenantId
ResourceManagerEndpoint = $ResourceManagerEndpoint
GalleryEndpoint = $endpoints.galleryEndpoint
GraphEndpoint = $endpoints.graphEndpoint
GraphAudience = $endpoints.graphEndpoint
AdTenant = $directoryTenantId
ResourceManagerEndpoint = $ResourceManagerEndpoint
GalleryEndpoint = $endpoints.galleryEndpoint
GraphEndpoint = $endpoints.graphEndpoint
GraphAudience = $endpoints.graphEndpoint
}
Remove-AzureRmEnvironment -Name $EnvironmentName -Force -ErrorAction Ignore | Out-Null
@ -157,30 +161,35 @@ function Resolve-AzureEnvironment([Microsoft.Azure.Commands.Profile.Models.PSAzu
return $azureEnvironment
}
function Initialize-AzureRmUserAccount([Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment]$azureEnvironment, [string] $SubscriptionName, [string] $SubscriptionId) {
# Prompts the user for interactive login flow
$azureAccount = Add-AzureRmAccount -EnvironmentName $azureEnvironment.Name -TenantId $azureEnvironment.AdTenant
function Initialize-AzureRmUserAccount([Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment]$azureEnvironment, [string] $SubscriptionName, [string] $SubscriptionId, [pscredential] $AutomationCredential) {
if ($SubscriptionName) {
$params = @{
EnvironmentName = $azureEnvironment.Name
TenantId = $azureEnvironment.AdTenant
}
if ($AutomationCredential)
{
$params += @{ Credential = $AutomationCredential }
}
# Prompts the user for interactive login flow if automation credential is not specified
$azureAccount = Add-AzureRmAccount @params
if ($SubscriptionName)
{
Select-AzureRmSubscription -SubscriptionName $SubscriptionName | Out-Null
}
elseif ($SubscriptionId) {
elseif ($SubscriptionId)
{
Select-AzureRmSubscription -SubscriptionId $SubscriptionId | Out-Null
}
return $azureAccount
}
function Get-IdentityApplicationData {
# Import and read application data
Write-Host "Loading identity application data..."
$xmlData = [xml](Get-ChildItem -Path C:\EceStore -Recurse -Force -File | Sort Length | Select -Last 1 | Get-Content | Out-String)
$xmlIdentityApplications = $xmlData.SelectNodes('//IdentityApplication')
return $xmlIdentityApplications
}
function Resolve-GraphEnvironment([Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment]$azureEnvironment) {
function Resolve-GraphEnvironment([Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment]$azureEnvironment)
{
$graphEnvironment = switch ($azureEnvironment.ActiveDirectoryAuthority) {
'https://login.microsoftonline.com/' { 'AzureCloud' }
'https://login.chinacloudapi.cn/' { 'AzureChinaCloud' }
@ -193,9 +202,20 @@ function Resolve-GraphEnvironment([Microsoft.Azure.Commands.Profile.Models.PSAzu
return $graphEnvironment
}
function Get-AzureRmUserRefreshToken([Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment]$azureEnvironment, [string]$directoryTenantId) {
# Prompts the user for interactive login flow
$azureAccount = Add-AzureRmAccount -EnvironmentName $azureEnvironment.Name -TenantId $directoryTenantId
function Get-AzureRmUserRefreshToken([Microsoft.Azure.Commands.Profile.Models.PSAzureEnvironment]$azureEnvironment, [string]$directoryTenantId, [pscredential]$AutomationCredential)
{
$params = @{
EnvironmentName = $azureEnvironment.Name
TenantId = $directoryTenantId
}
if ($AutomationCredential)
{
$params += @{ Credential = $AutomationCredential }
}
# Prompts the user for interactive login flow if automation credential is not specified
$azureAccount = Add-AzureRmAccount @params
# Retrieve the refresh token
$tokens = [Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache]::DefaultShared.ReadItems()
@ -203,12 +223,15 @@ function Get-AzureRmUserRefreshToken([Microsoft.Azure.Commands.Profile.Models.PS
Where Resource -EQ $azureEnvironment.ActiveDirectoryServiceEndpointResourceId |
Where IsMultipleResourceRefreshToken -EQ $true |
Where DisplayableId -EQ $azureAccount.Context.Account.Id |
Select -ExpandProperty RefreshToken |
Sort ExpiresOn |
Select -Last 1 -ExpandProperty RefreshToken |
ConvertTo-SecureString -AsPlainText -Force
return $refreshToken
}
# Exposed Functions
<#
.Synopsis
Adds a Guest Directory Tenant to Azure Stack.
@ -219,9 +242,10 @@ function Get-AzureRmUserRefreshToken([Microsoft.Azure.Commands.Profile.Models.PS
$azureStackDirectoryTenant = "<homeDirectoryTenant>.onmicrosoft.com"
$guestDirectoryTenantToBeOnboarded = "<guestDirectoryTenant>.onmicrosoft.com"
Register-GuestDirectoryTenantToAzureStack -AdminResourceManagerEndpoint $adminARMEndpoint -DirectoryTenantName $azureStackDirectoryTenant -GuestDirectoryTenantName $guestDirectoryTenantToBeOnboarded
Register-AzsGuestDirectoryTenant -AdminResourceManagerEndpoint $adminARMEndpoint -DirectoryTenantName $azureStackDirectoryTenant -GuestDirectoryTenantName $guestDirectoryTenantToBeOnboarded
#>
function Register-GuestDirectoryTenantToAzureStack {
function Register-AzsGuestDirectoryTenant {
[CmdletBinding()]
param
(
@ -236,10 +260,15 @@ function Register-GuestDirectoryTenantToAzureStack {
[ValidateNotNullOrEmpty()]
[string] $DirectoryTenantName,
# The name of the guest Directory Tenant which is to be onboarded.
# The names of the guest Directory Tenants which are to be onboarded.
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $GuestDirectoryTenantName,
[string[]] $GuestDirectoryTenantName,
# The location of your Azure Stack deployment.
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $Location,
# The identifier of the Administrator Subscription. If not specified, the script will attempt to use the set default subscription.
[ValidateNotNull()]
@ -253,9 +282,10 @@ function Register-GuestDirectoryTenantToAzureStack {
[ValidateNotNullOrEmpty()]
[string] $ResourceGroupName = 'system',
# Optional: A credential used to authenticate with Azure Stack. Must support a non-interactive authentication flow. If not provided, the script will prompt for user credentials.
[Parameter()]
[ValidateNotNullOrEmpty()]
[string] $Location = 'local'
[ValidateNotNull()]
[pscredential] $AutomationCredential = $null
)
$ErrorActionPreference = 'Stop'
$VerbosePreference = 'Continue'
@ -265,137 +295,29 @@ function Register-GuestDirectoryTenantToAzureStack {
# Initialize the Azure PowerShell module to communicate with Azure Stack. Will prompt user for credentials.
$azureEnvironment = Initialize-AzureRmEnvironment -EnvironmentName 'AzureStackAdmin' -ResourceManagerEndpoint $AdminResourceManagerEndpoint -DirectoryTenantName $DirectoryTenantName
$azureAccount = Initialize-AzureRmUserAccount -azureEnvironment $azureEnvironment -SubscriptionName $SubscriptionName -SubscriptionId $SubscriptionId
$azureAccount = Initialize-AzureRmUserAccount -azureEnvironment $azureEnvironment -SubscriptionName $SubscriptionName -SubscriptionId $SubscriptionId -AutomationCredential $AutomationCredential
# resolve the guest directory tenant ID from the name
$guestDirectoryTenantId = (New-Object uri(Invoke-RestMethod "$($azureEnvironment.ActiveDirectoryAuthority.TrimEnd('/'))/$GuestDirectoryTenantName/.well-known/openid-configuration").token_endpoint).AbsolutePath.Split('/')[1]
# Add (or update) the new directory tenant to the Azure Stack deployment
$params = @{
ApiVersion = '2015-11-01' # needed if using "latest" / later version of Azure Powershell
ResourceType = "Microsoft.Subscriptions.Admin/directoryTenants"
ResourceGroupName = $ResourceGroupName
ResourceName = $GuestDirectoryTenantName
Location = $Location
Properties = @{ tenantId = $guestDirectoryTenantId }
}
$directoryTenant = New-AzureRmResource @params -Force -Verbose -ErrorAction Stop
Write-Verbose -Message "Directory Tenant onboarded: $(ConvertTo-Json $directoryTenant)" -Verbose
}
<#
.Synopsis
Publishes the list of applications to the Azure Stack ARM.
.DESCRIPTION
.EXAMPLE
$adminARMEndpoint = "https://adminmanagement.local.azurestack.external"
$azureStackDirectoryTenant = "<homeDirectoryTenant>.onmicrosoft.com"
$guestDirectoryTenantToBeOnboarded = "<guestDirectoryTenant>.onmicrosoft.com"
Publish-AzureStackApplicationsToARM -AdminResourceManagerEndpoint $adminARMEndpoint -DirectoryTenantName $azureStackDirectoryTenant
#>
function Publish-AzureStackApplicationsToARM {
[CmdletBinding()]
param
(
# The endpoint of the Azure Stack Resource Manager service.
[Parameter(Mandatory = $true)]
[ValidateNotNull()]
[ValidateScript( {$_.Scheme -eq [System.Uri]::UriSchemeHttps})]
[uri] $AdminResourceManagerEndpoint,
# The name of the home Directory Tenant in which the Azure Stack Administrator subscription resides.
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $DirectoryTenantName,
# The identifier of the Administrator Subscription. If not specified, the script will attempt to use the set default subscription.
[Parameter()]
[ValidateNotNull()]
[string] $SubscriptionId = $null,
# The display name of the Administrator Subscription. If not specified, the script will attempt to use the set default subscription.
[Parameter()]
[ValidateNotNull()]
[string] $SubscriptionName = $null,
[Parameter()]
[ValidateNotNullOrEmpty()]
[string] $ResourceGroupName = 'system',
[Parameter()]
[ValidateNotNullOrEmpty()]
[string] $Location = 'local',
[Parameter()]
[ValidateNotNullOrEmpty()]
[ValidateScript( {Test-Path -Path $_ -PathType Container -ErrorAction Stop})]
[string] $InfrastructureSharePath = '\\SU1FileServer\SU1_Infrastructure_1'
)
$ErrorActionPreference = 'Stop'
$VerbosePreference = 'Continue'
# Install-Module AzureRm -RequiredVersion '1.2.8'
Import-Module 'AzureRm.Profile' -Force -Verbose:$false 4> $null
Write-Warning "This script is intended to work only with the initial TP3 release of Azure Stack and will be deprecated."
# Initialize the Azure PowerShell module to communicate with Azure Stack. Will prompt user for credentials.
$azureEnvironment = Initialize-AzureRmEnvironment -EnvironmentName 'AzureStackAdmin' -ResourceManagerEndpoint $AdminResourceManagerEndpoint -DirectoryTenantName $DirectoryTenantName
$azureAccount = Initialize-AzureRmUserAccount -azureEnvironment $azureEnvironment -SubscriptionName $SubscriptionName -SubscriptionId $SubscriptionId
# Register each identity application for future onboarding.
$xmlIdentityApplications = Get-IdentityApplicationData
foreach ($xmlIdentityApplication in $xmlIdentityApplications) {
$applicationData = Get-Content -Path ($xmlIdentityApplication.ConfigPath.Replace('{Infrastructure}', $InfrastructureSharePath)) | Out-String | ConvertFrom-Json
# Note - 'Admin' applications do not need to be registered for replication into a new directory tenant
if ($xmlIdentityApplication.Name.StartsWith('Admin', [System.StringComparison]::OrdinalIgnoreCase)) {
Write-Warning "Skipping registration of Admin application: $('{0}.{1}' -f $xmlIdentityApplication.Name, $xmlIdentityApplication.DisplayName)"
continue
}
# Advertise any necessary OAuth2PermissionGrants for the application
$oauth2PermissionGrants = @()
foreach ($applicationFriendlyName in $xmlIdentityApplication.OAuth2PermissionGrants.FirstPartyApplication.FriendlyName) {
$oauth2PermissionGrants += [pscustomobject]@{
Resource = $applicationData.ApplicationInfo.appId
Client = $applicationData.GraphInfo.Applications."$applicationFriendlyName".Id
ConsentType = 'AllPrincipals'
Scope = 'user_impersonation'
}
}
foreach ($directoryTenantName in $GuestDirectoryTenantName)
{
# Resolve the guest directory tenant ID from the name
$directoryTenantId = (New-Object uri(Invoke-RestMethod "$($azureEnvironment.ActiveDirectoryAuthority.TrimEnd('/'))/$directoryTenantName/.well-known/openid-configuration").token_endpoint).AbsolutePath.Split('/')[1]
# Add (or update) the new directory tenant to the Azure Stack deployment
$params = @{
ApiVersion = '2015-11-01' # needed if using "latest" / later version of Azure Powershell
ResourceType = "Microsoft.Subscriptions.Providers/applicationRegistrations"
ApiVersion = '2015-11-01'
ResourceType = "Microsoft.Subscriptions.Admin/directoryTenants"
ResourceGroupName = $ResourceGroupName
ResourceName = '{0}.{1}' -f $xmlIdentityApplication.Name, $xmlIdentityApplication.DisplayName
Location = $Location
Properties = @{
"objectId" = $applicationData.ApplicationInfo.objectId
"appId" = $applicationData.ApplicationInfo.appId
"oauth2PermissionGrants" = $oauth2PermissionGrants
"directoryRoles" = @()
"tags" = @()
}
ResourceName = $directoryTenantName
Location = $Location
Properties = @{ tenantId = $directoryTenantId }
}
# Advertise 'ReadDirectoryData' workaround for applications which require this permission of type 'Role'
if ($xmlIdentityApplication.AADPermissions.ApplicationPermission.Name -icontains 'ReadDirectoryData') {
$params.Properties.directoryRoles = @('Directory Readers')
}
# Advertise any specified tags required for application integration scenarios
if ($xmlIdentityApplication.tags) {
$params.Properties.tags += $xmlIdentityApplication.tags
}
$registeredApplication = New-AzureRmResource @params -Force -Verbose -ErrorAction Stop
Write-Verbose -Message "Identity application registered: $(ConvertTo-Json $registeredApplication)" -Verbose
$directoryTenant = New-AzureRmResource @params -Force -Verbose -ErrorAction Stop
Write-Verbose -Message "Directory Tenant onboarded: $(ConvertTo-Json $directoryTenant)" -Verbose
}
}
Export-ModuleMember -Function 'Publish-AzsApplicationsToARM'
<#
.Synopsis
Consents to the given Azure Stack instance within the callers's Azure Directory Tenant.
@ -405,10 +327,11 @@ Consents to the given Azure Stack instance within the callers's Azure Directory
$tenantARMEndpoint = "https://management.local.azurestack.external"
$myDirectoryTenantName = "<guestDirectoryTenant>.onmicrosoft.com"
Register-AzureStackWithMyDirectoryTenant -TenantResourceManagerEndpoint $tenantARMEndpoint `
Register-AzsWithMyDirectoryTenant -TenantResourceManagerEndpoint $tenantARMEndpoint `
-DirectoryTenantName $myDirectoryTenantName -Verbose -Debug
#>
function Register-AzureStackWithMyDirectoryTenant {
function Register-AzsWithMyDirectoryTenant {
[CmdletBinding()]
param
(
@ -421,7 +344,17 @@ function Register-AzureStackWithMyDirectoryTenant {
# The name of the directory tenant being onboarded.
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string] $DirectoryTenantName
[string] $DirectoryTenantName,
# Optional: The identifier (GUID) of the Resource Manager application. Pass this parameter to skip the need to complete the guest signup flow via the portal.
[Parameter(Mandatory=$false)]
[ValidateNotNullOrEmpty()]
[string] $ResourceManagerApplicationId,
# Optional: A credential used to authenticate with Azure Stack. Must support a non-interactive authentication flow. If not provided, the script will prompt for user credentials.
[Parameter()]
[ValidateNotNull()]
[pscredential] $AutomationCredential = $null
)
$ErrorActionPreference = 'Stop'
@ -429,50 +362,97 @@ function Register-AzureStackWithMyDirectoryTenant {
# Install-Module AzureRm -RequiredVersion '1.2.8'
Import-Module 'AzureRm.Profile' -Force -Verbose:$false 4> $null
Import-Module "$PSScriptRoot\GraphAPI\GraphAPI.psm1" -Force -Verbose:$false 4> $null
Import-Module "$PSScriptRoot\GraphAPI\GraphAPI.psm1" -Force -Verbose:$false 4> $null
# Initialize the Azure PowerShell module to communicate with the Azure Resource Manager corresponding to their home Graph Service. Will prompt user for credentials.
$azureStackEnvironment = Initialize-AzureRmEnvironment -EnvironmentName 'AzureStack' -ResourceManagerEndpoint $TenantResourceManagerEndpoint -DirectoryTenantName $DirectoryTenantName
$azureEnvironment = Resolve-AzureEnvironment $azureStackEnvironment
$refreshToken = Get-AzureRmUserRefreshToken $azureEnvironment $azureStackEnvironment.AdTenant
$refreshToken = Get-AzureRmUserRefreshToken -azureEnvironment $azureEnvironment -directoryTenantId $azureStackEnvironment.AdTenant -AutomationCredential $AutomationCredential
# Initialize the Graph PowerShell module to communicate with the correct graph service
$graphEnvironment = Resolve-GraphEnvironment $azureEnvironment
$graphEnvironment = ResolveGraphEnvironment $azureEnvironment
Initialize-GraphEnvironment -Environment $graphEnvironment -DirectoryTenantId $DirectoryTenantName -RefreshToken $refreshToken
# Initialize the service principal for the Azure Stack Resource Manager application (allows us to acquire a token to ARM). If not specified, the sign-up flow must be completed via the Azure Stack portal first.
if ($ResourceManagerApplicationId)
{
$resourceManagerServicePrincipal = Initialize-GraphApplicationServicePrincipal -ApplicationId $ResourceManagerApplicationId
}
# Authorize the Azure Powershell module to act as a client to call the Azure Stack Resource Manager in the onboarding directory tenant
Initialize-GraphOAuth2PermissionGrant -ClientApplicationId (Get-GraphEnvironmentInfo).Applications.PowerShell.Id -ResourceApplicationIdentifierUri $azureStackEnvironment.ActiveDirectoryServiceEndpointResourceId
Write-Host "Delaying for 15 seconds to allow the permission for Azure PowerShell to be initialized..."
Start-Sleep -Seconds 15
# Authorize the Azure Powershell module to act as a client to call the Azure Stack Resource Manager in the onboarded tenant
Initialize-GraphOAuth2PermissionGrant -ClientApplicationId (Get-GraphEnvironmentInfo).Applications.PowerShell.Id -ResourceApplicationIdentifierUri $azureStackEnvironment.ActiveDirectoryServiceEndpointResourceId
# Call Azure Stack Resource Manager to retrieve the list of registered applications which need to be initialized in the onboarding directory tenant
$armAccessToken = (Get-GraphToken -Resource $azureStackEnvironment.ActiveDirectoryServiceEndpointResourceId -UseEnvironmentData).access_token
$applicationRegistrationParams = @{
Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get
Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get
Headers = @{ Authorization = "Bearer $armAccessToken" }
Uri = "$($TenantResourceManagerEndpoint.ToString().TrimEnd('/'))/applicationRegistrations?api-version=2014-04-01-preview"
Uri = "$($TenantResourceManagerEndpoint.ToString().TrimEnd('/'))/applicationRegistrations?api-version=2014-04-01-preview"
}
$applicationRegistrations = Invoke-RestMethod @applicationRegistrationParams | Select -ExpandProperty value
$applicationRegistrations = Invoke-RestMethod @applicationRegistrationParams | Select-Object -ExpandProperty value
# Initialize each registered application in the onboarding directory tenant
foreach ($applicationRegistration in $applicationRegistrations) {
# Initialize the service principal for the registered application, updating any tags as necessary
# Identify which permissions have already been granted to each registered application and which additional permissions need consent
$permissions = @()
foreach ($applicationRegistration in $applicationRegistrations)
{
# Initialize the service principal for the registered application
$applicationServicePrincipal = Initialize-GraphApplicationServicePrincipal -ApplicationId $applicationRegistration.appId
if ($applicationRegistration.tags) {
# Initialize the necessary tags for the registered application
if ($applicationRegistration.tags)
{
Update-GraphApplicationServicePrincipalTags -ApplicationId $applicationRegistration.appId -Tags $applicationRegistration.tags
}
# Initialize the necessary oauth2PermissionGrants for the registered application
foreach ($oauth2PermissionGrant in $applicationRegistration.oauth2PermissionGrants) {
$oauth2PermissionGrantParams = @{
ClientApplicationId = $oauth2PermissionGrant.client
ResourceApplicationId = $oauth2PermissionGrant.resource
Scope = $oauth2PermissionGrant.scope
# Lookup the permission consent status for the application permissions (either to or from) that the registered application requires
foreach($appRoleAssignment in $applicationRegistration.appRoleAssignments)
{
$params = @{
ClientApplicationId = $appRoleAssignment.client
ResourceApplicationId = $appRoleAssignment.resource
PermissionType = 'Application'
PermissionId = $appRoleAssignment.roleId
}
Initialize-GraphOAuth2PermissionGrant @oauth2PermissionGrantParams
$permissions += New-GraphPermissionDescription @params -LookupConsentStatus
}
# Initialize the necessary directory role membership(s) for the registered application
foreach ($directoryRole in $applicationRegistration.directoryRoles) {
Initialize-GraphDirectoryRoleMembership -ApplicationId $applicationRegistration.appId -RoleDisplayName $directoryRole
# Lookup the permission consent status for the delegated permissions (either to or from) that the registered application requires
foreach($oauth2PermissionGrant in $applicationRegistration.oauth2PermissionGrants)
{
$resourceApplicationServicePrincipal = Initialize-GraphApplicationServicePrincipal -ApplicationId $oauth2PermissionGrant.resource
foreach ($scope in $oauth2PermissionGrant.scope.Split(' '))
{
$params = @{
ClientApplicationId = $oauth2PermissionGrant.client
ResourceApplicationServicePrincipal = $resourceApplicationServicePrincipal
PermissionType = 'Delegated'
PermissionId = ($resourceApplicationServicePrincipal.oauth2Permissions | Where value -EQ $scope).id
}
$permissions += New-GraphPermissionDescription @params -LookupConsentStatus
}
}
}
# Show the user a display of the required permissions
$permissions | Show-GraphApplicationPermissionDescriptions
if ($permissions | Where isConsented -EQ $false | Select -First 1)
{
# Grant the required permissions to the corresponding applications
$permissions | Where isConsented -EQ $false | Grant-GraphApplicationPermission
}
Write-Host "`r`nAll permissions required for registered Azure Stack applications or scenarios have been granted!" -ForegroundColor Green
}
Export-ModuleMember -Function @(
"Register-AzureStackWithMyDirectoryTenant",
"Register-GuestDirectoryTenantToAzureStack",
"Get-DirectoryTenantIdentifier",
"New-AzsADGraphServicePrincipal"
)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,7 +1,7 @@
# Azure Stack Identity
```powershell
Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
// Place your settings in this file to overwrite the default settings
{
"workbench.colorTheme": "Abyss"
}nstall-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.9 -Scope CurrentUser
```
@ -18,7 +18,7 @@ Import-Module ..\Identity\AzureStack.Identity.psm1
This function is used to get the Directory Tenant Guid. This method works for both AAD and AD FS.
```powershell
$directoryTenantId = Get-DirectoryTenantIdentifier -Authority "<DirectoryTenantUrl>"
$directoryTenantId = Get-AzsDirectoryTenantIdentifier -Authority "<DirectoryTenantUrl>"
```
An example of an authority for AAD is `https://login.windows.net/microsoft.onmicrosoft.com`
@ -29,7 +29,7 @@ and for AD FS is `https://adfs.local.azurestack.external/adfs`.
You can create a Service Principal by executing the following command after importing the Identity module
```powershell
$servicePrincipal = New-ADGraphServicePrincipal -DisplayName "<YourServicePrincipalName>" -AdminCredential $(Get-Credential) -Verbose
$servicePrincipal = New-AzsAdGraphServicePrincipal -DisplayName "<YourServicePrincipalName>" -AdminCredential $(Get-Credential) -Verbose
```
After the Service Principal is created, you should open your Azure Stack Portal to provide the appropriate level of RBAC to it. You can do this from the Access Control (IAM) tab of any resource. After the RBAC is given, you can login using the service principal as follows:
@ -48,22 +48,6 @@ There are two personas involved in implementing this scenario.
### Azure Stack Administrator
#### Pre-Requisite: Populate Azure Resource Manager with AzureStack Applications
- This step is a temporary workaround and needed only for the TP3 (March) release of Azure Stack
- Execute this cmdlet as the **Azure Stack Service Administrator**, from the Console VM or the DVM replacing ```$azureStackDirectoryTenant``` with the directory tenant that Azure Stack is registered to and ```$guestDirectoryTenant``` with the directory that needs to be onboarded to Azure Stack.
__NOTE:__ This cmd needs to be run **only once** throughout the entire life cycle of that Azure Stack installation. You do **not** have to run this step every time you need to add a new directory.
```powershell
$adminARMEndpoint = "https://adminmanagement.<region>.<domain>"
$azureStackDirectoryTenant = "<homeDirectoryTenant>.onmicrosoft.com"
$guestDirectoryTenantToBeOnboarded = "<guestDirectoryTenant>.onmicrosoft.com"
Publish-AzureStackApplicationsToARM -AdminResourceManagerEndpoint $adminARMEndpoint `
-DirectoryTenantName $azureStackDirectoryTenant
```
#### Step 1: Onboard the Guest Directory Tenant to Azure Stack
This step will let Azure Resource manager know that it can accept users and service principals from the guest directory tenant.
@ -72,9 +56,11 @@ This step will let Azure Resource manager know that it can accept users and serv
$adminARMEndpoint = "https://adminmanagement.<region>.<domain>"
$azureStackDirectoryTenant = "<homeDirectoryTenant>.onmicrosoft.com" # this is the primary tenant Azure Stack is registered to
$guestDirectoryTenantToBeOnboarded = "<guestDirectoryTenant>.onmicrosoft.com" # this is the new tenant that needs to be onboarded to Azure Stack
$location = "local"
Register-GuestDirectoryTenantToAzureStack -AdminResourceManagerEndpoint $adminARMEndpoint `
-DirectoryTenantName $azureStackDirectoryTenant -GuestDirectoryTenantName $guestDirectoryTenantToBeOnboarded
-DirectoryTenantName $azureStackDirectoryTenant `
-GuestDirectoryTenantName $guestDirectoryTenantToBeOnboarded `
-Location $location
```
With this step, the work of the Azure Stack administrator is done.
@ -85,7 +71,7 @@ The following steps need to be completed by the **Directory Tenant Administrator
#### Step 2: Providing UI-based consent to Azure Stack Portal and ARM
- This is an important step. Open up a web browser, and go to `https://portal.<region>.<domain>/guest/signup/<guestDirectoryName>`. Note that this is the directory tenant that needs to be onboarded to Azure Stack.
- This is an important step. Open up a web browser, and go to `https://portal.<region>.<domain>/guest/signup/<guestDirectoryName>`. Note that this is the directory tenant that needs to be onboarded to Azure Stack.
- This will take you to an AAD sign in page where you need to enter your credentials and click on 'Accept' on the consent screen.
#### Step 3: Registering Azure Stack applications with the Guest Directory
@ -97,5 +83,5 @@ $tenantARMEndpoint = "https://management.<region>.<domain>"
$guestDirectoryTenantName = "<guestDirectoryTenant>.onmicrosoft.com" # this is the new tenant that needs to be onboarded to Azure Stack
Register-AzureStackWithMyDirectoryTenant -TenantResourceManagerEndpoint $tenantARMEndpoint `
-DirectoryTenantName $guestDirectoryTenantName -Verbose -Debug
-DirectoryTenantName $guestDirectoryTenantName
```

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Двоичные данные
Infrastructure/InfraAlertsVideo.gif Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.8 MiB

Просмотреть файл

@ -3,12 +3,7 @@
Instructions below are relative to the .\Infrastructure folder of the [AzureStack-Tools repo](..).
This also requires the Azure Stack Connect Module to be imported before running any of the commands. The Module can also be found in the [AzureStack-Tools repo](..).
Whats new for TP3:
- New Cmdlet Name Prefix
- API Resource Name changes
- New cmdlets
- Use of Azure Stack Connect Module
![Using infrastructure cmdlets against Azure Stack](/Infrastructure/InfraAlertsVideo.gif)
## Import the Module
@ -17,32 +12,29 @@ Import-Module .\AzureStack.Infra.psm1
```
## Add PowerShell environment
```powershell
Import-Module .\AzureStack.Connect.psm1
```
You will need to reference your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
You will need to login to your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
```powershell
Add-AzureStackAzureRmEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
```
Connecting to your environment requires that you obtain the value of your Directory Tenant ID. For **Azure Active Directory** environments provide your directory tenant name:
```powershell
$TenantID = Get-DirectoryTenantID -AADTenantName "<mydirectorytenant>.onmicrosoft.com" -EnvironmentName AzureStackAdmin
```
For **ADFS** environments use the following:
```powershell
$TenantID = Get-DirectoryTenantID -ADFS -EnvironmentName AzureStackAdmin
Add-AzureRMEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
```
Then login:
```powershell
Login-AzureRmAccount -EnvironmentName "AzureStackAdmin" -TenantId $TenantID
Login-AzureRmAccount -EnvironmentName "AzureStackAdmin"
```
----
If you are **not** using your home directory tenant, you will need to supply the tenant ID to your login command. You may find it easiest to obtain using the Connect tool. For **Azure Active Directory** environments provide your directory tenant name:
```powershell
$TenantID = Get-AzsDirectoryTenantId -AADTenantName "<mydirectorytenant>.onmicrosoft.com" -EnvironmentName AzureStackAdmin
```
For **ADFS** environments use the following:
```powershell
$TenantID = Get-AzsDirectoryTenantId -ADFS -EnvironmentName AzureStackAdmin
```
## Individual Command Usage
@ -54,406 +46,356 @@ Explains each individual command and shows how to use it
List active and closed Infrastructure Alerts
```powershell
$credential = Get-Credential
Get-AzSAlert -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsAlert
```
Note: The cmdlet requires credentials to retrieve Alerts. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Retrieves Active & Closed Alerts
### Close Infrastructure Alerts
Close any active Infrastructure Alert. Run Get-AzureStackAlert to get the AlertID, required to close a specific Alert.
Close any active Infrastructure Alert. Run Get-AzsAlert to get the AlertID, required to close a specific Alert.
```powershell
$credential = Get-Credential
Close-AzSAlert -AzureStackCredentials $credential -TenantID $TenantID -AlertID "ID" -EnvironmentName "AzureStackAdmin"
Close-AzsAlert -AlertID "ID"
```
Note: The cmdlet requires credentials to close active Alert. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Close active Alert
### Get Region Update Summary
Review the Update Summary for a specified region.
```powershell
$credential = Get-Credential
Get-AzSUpdateSummary -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsUpdateSummary
```
Note: The cmdlet requires credentials to retrieve Region Update Summary. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Retrieves Region Update Summary
### Get Azure Stack Update
Retrieves list of Azure Stack Updates
```powershell
$credential = Get-Credential
Get-AzSUpdate -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsUpdate
```
Note: The cmdlet requires credentials to retrieve Azure Stack Updates. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- List Azure Stack Updates
### Apply Azure Stack Update
Applies a specific Azure Stack Update that is downloaded and applicable. Run Get-AzureStackUpdate to retrieve Update Version first
```powershell
$credential = Get-Credential
Install-AzSUpdate -AzureStackCredentials $credential -TenantID $TenantID -vupdate "Update Version" -EnvironmentName "AzureStackAdmin"
Install-AzsUpdate -Update "Update Version"
```
Note: The cmdlet requires credentials to apply a specific Update. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Applies specified Update
### Get Azure Stack Update Run
Should be used to validate a specific Update Run or look at previous update runs
```powershell
$credential = Get-Credential
Get-AzSUpdateRun -AzureStackCredentials $credential -TenantID $TenantID -vupdate "Update Version" -EnvironmentName "AzureStackAdmin"
Get-AzsUpdateRun -Update "Update Version"
```
Note: The cmdlet requires credentials to retrieve Update Run information. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Lists Update Run information for a specific Azure Stack update
### List Infrastructure Roles
Does list all Infrastructure Roles
```powershell
$credential = Get-Credential
Get-AzSInfraRole -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsInfrastructureRole
```
Note: The cmdlet requires credentials to retrieve Infrastructure Roles. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Lists Infrastructure Roles
### List Infrastructure Role Instance
Does list all Infrastructure Role Instances (Note: Does not return Directory Management VM in One Node deployment)
```powershell
$credential = Get-Credential
Get-AzSInfraRoleInstance -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsInfrastructureRoleInstance
```
Note: The cmdlet requires credentials to retrieve Infrastructure Role Instances. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Lists Infrastructure Role Instances
### List Scale Unit
Does list all Scale Units in a specified Region
```powershell
$credential = Get-Credential
Get-AzSScaleUnit -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsScaleUnit
```
Note: The cmdlet requires credentials to retrieve Scale Units. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Lists Scale Units
### List Scale Unit Nodes
Does list all Scale Units Nodes
```powershell
$credential = Get-Credential
Get-AzSScaleUnitNode -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsScaleUnitNode
```
Note: The cmdlet requires credentials to retrieve all Scale Unit Nodes. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Lists Scale Unit Nodes
### List Logical Networks
Does list all logical Networks by ID
```powershell
$credential = Get-Credential
Get-AzSLogicalNetwork -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsLogicalNetwork
```
Note: The cmdlet requires credentials to retrieve logical Networks. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Lists logical Networks
### List Storage Capacity
Does return the total capacity of the storage subsystem
```powershell
$credential = Get-Credential
Get-AzSStorageCapacity -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsStorageCapacity
```
Note: The cmdlet requires credentials to retrieve total storage capacity. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Lists total storage capacity for the storage subsystem
### List Storage Shares
Does list all file shares in the storage subsystem
```powershell
$credential = Get-Credential
Get-AzSStorageShare -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsStorageShare
```
Note: The cmdlet requires credentials to retrieve file shares. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Retrieves all file shares
### List IP Pools
Does list all IP Pools
```powershell
$credential = Get-Credential
Get-AzSIPPool -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsIpPool
```
Note: The cmdlet requires credentials to retrieve IP Pools. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Retrieves all IP Pools
### List MAC Address Pools
Does list all MAC Address Pool
```powershell
$credential = Get-Credential
Get-AzSMacPool -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsMacPool
```
Note: The cmdlet requires credentials to retrieve all MAC Address Pools. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Retrieves all MAC Address Pools
### List Gateway Pools
Does list all Gateway Pools
```powershell
$credential = Get-Credential
Get-AzSGatewayPool -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsGatewayPool
```
Note: The cmdlet requires credentials to retrieve the Gateway Pools. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Retrieves all Gateway Pools
### List SLB MUX
Does list all SLB MUX Instances
```powershell
$credential = Get-Credential
Get-AzSSLBMUX -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzSLBMux
```
Note: The cmdlet requires credentials to retrieve all SLB MUX instances. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Retrieves all SLB MUX instances
### List Gateway Instances
Does list all Gateway Instances
```powershell
$credential = Get-Credential
Get-AzSGateway -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsGateway
```
Note: The cmdlet requires credentials to retrieve all Gateway instances. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Retrieves all Gateway instances
### Start Infra Role Instance
Does start an Infra Role Instance
```powershell
$credential = Get-Credential
Start-AzSInfraRoleInstance -AzureStackCredentials $credential -TenantID $TenantID -Name "InfraRoleInstanceName" -EnvironmentName "AzureStackAdmin"
Start-AzsInfrastructureRoleInstance -Name "InfraRoleInstanceName"
```
Note: The cmdlet requires credentials to start an infra role instance. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Starts an Infra Role instance
### Stop Infra Role Instance
Does stop an Infra Role Instance
```powershell
$credential = Get-Credential
Stop-AzSInfraRoleInstance -AzureStackCredentials $credential -TenantID $TenantID -Name "InfraRoleInstanceName" -EnvironmentName "AzureStackAdmin"
Stop-AzsInfrastructureRoleInstance -Name "InfraRoleInstanceName"
```
Note: The cmdlet requires credentials to stop an infra role instance. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Stops an Infra Role instance
### Restart Infra Role Instance
Does restart an Infra Role Instance
Does Restart an Infra Role Instance
```powershell
$credential = Get-Credential
Restart-AzSInfraRoleInstance -AzureStackCredentials $credential -TenantID $TenantID -Name "InfraRoleInstanceName" -EnvironmentName "AzureStackAdmin"
Restart-AzsInfrastructureRoleInstance -Name "InfraRoleInstanceName"
```
Note: The cmdlet requires credentials to restart an infra role instance. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Restart an Infra Role instance
### Add IP Pool
Does add an IP Pool
```powershell
$credential = Get-Credential
Add-AzSIPPool -AzureStackCredentials $credential -TenantID $TenantID -Name "PoolName" -StartIPAddress "192.168.55.1" -EndIPAddress "192.168.55.254" -AddressPrefix "192.168.0./24" -EnvironmentName "AzureStackAdmin"
Add-AzsIpPool -Name "PoolName" -StartIPAddress "192.168.55.1" -EndIPAddress "192.168.55.254" -AddressPrefix "192.168.0./24"
```
Note: The cmdlet requires credentials to add an IP Pool. Provide the administrator Azure Active Directory credentials, such as *&lt;Admin Account&gt;*@*&lt;mydirectory&gt;*.onmicrosoft.com or the ADFS credentials, to the prompt.
The command does the following:
- Authenticates to the Azure Stack environment
- Adds an IP Pool
### Enable Maintenance Mode
Does put a ScaleUnitNode in Maintenance Mode
```powershell
Disable-AzsScaleUnitNode -Name NodeName
```
The command does the following:
- Enables Maintenance Mode for a specified ScaleUnitNode
### Disable Maintenance Mode
Does resume a ScaleUnitNode from Maintenance Mode
```powershell
Enable-AzsScaleUnitNode -Name NodeName
```
The command does the following:
- Resume from Maintenance Mode for a specified ScaleUnitNode
### Show Region Capacity
Does show capacity for specified Region
```powershell
Get-AzsLocationCapacity
```
The command does the following:
- Retrieves Region Capacity information
## Scenario Command Usage
Demonstrates using multiple commands together for an end to end scenario.
### Recover an Infrastructure Role Instance that has an Alert assigned.
### Recover an Infrastructure Role Instance that has an Alert assigned
```powershell
#Retrieve all Alerts and apply a filter to only show active Alerts
$Active=Get-AzSAlert -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"|where {$_.state -eq "active"}
$Active=Get-AzsAlert | Where {$_.State -eq "active"}
$Active
#Stop Infra Role Instance
Stop-AzSInfraRoleInstance -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin" -Name $Active.resourceName
Stop-AzsInfrastructureRoleInstance -Name $Active.ResourceName
#Start Infra Role Instance
Start-AzSInfraRoleInstance -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin" -Name $Active.resourceName
Start-AzsInfrastructureRoleInstance -Name $Active.resourceName
#Validate if error is resolved (Can take up to 3min)
Get-AzSAlert -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"|where {$_.state -eq "active"}
Get-AzsAlert | Where {$_.State -eq "active"}
```
### Increase Public IP Pool Capacity
```powershell
#Retrieve all Alerts and apply a filter to only show active Alerts
$Active=Get-AzSAlert -AzureStackCredentials $cred -TenantID $TenantID -EnvironmentName "AzureStackAdmin"|where {$_.state -eq "active"}
$Active=Get-AzsAlert | Where {$_.State -eq "active"}
$Active
#Review IP Pool Allocation
Get-AzSIPPool -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsIpPool
#Add New Public IP Pool
Add-AzSIPPool -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin" -Name "NewPublicIPPool" -StartIPAddress "192.168.80.0" -EndIPAddress "192.168.80.255" -AddressPrefix "192.168.80.0/24"
Add-AzsIpPool -Name "NewPublicIPPool" -StartIPAddress "192.168.80.0" -EndIPAddress "192.168.80.255" -AddressPrefix "192.168.80.0/24"
#Validate new IP Pool
Get-AzSIPPool -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsIpPool
```
### Apply Update to Azure Stack
```powershell
#Review Current Region Update Summary
Get-AzSUpdateSummary -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsUpdateSummary
#Check for available and applicable updates
Get-AzSUpdate -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsUpdate
#Apply Update
Install-AzSUpdate -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin" -vupdate "2.0.0.0"
Install-AzsUpdate -Update "2.0.0.0"
#Check Update Run
Get-AzSUpdateRun -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin" -vupdate "2.0.0.0"
Get-AzsUpdateRun -Update "2.0.0.0"
#Review Region Update Summary after successful run
Get-AzSUpdateSummary -AzureStackCredentials $credential -TenantID $TenantID -EnvironmentName "AzureStackAdmin"
Get-AzsUpdateSummary
```
### Perform FRU procedure
```powershell
#Review current ScaleUnitNode State
$node=Get-AzsScaleUnitNode
$node | fl
#Enable Maintenance Mode for that node which drains all active resources
Disable-AzsScaleUnitNode -Name $node.name
#Power Off Server using build in KVN or physical power button
#BMC IP Address is returned by previous command $node.properties | fl
#Apply FRU Procedure
#Power On Server using build in KVN or physical power button
#Resume ScaleUnitNode from Maintenance Mode
Enable-AzsScaleUnitNode -Name $node.name
#Validate ScaleUnitNode Status
$node=Get-AzsScaleUnitNode
$node | fl
```
### Set Azure Stack's Latitude and Longitude
@ -468,7 +410,6 @@ $latitude = '12.972442'
$longitude = '77.580643'
$regionName = 'local'
$TenantID = Get-DirectoryTenantID -AADTenantName $directoryName -EnvironmentName AzureStackAdmin
Set-AzSLocationInformation -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $credential -Region $regionName -Latitude $latitude -Longitude $longitude
Set-AzsLocationInformation -Region $regionName -Latitude $latitude -Longitude $longitude
```

Просмотреть файл

@ -11,8 +11,8 @@ Describe $script:ModuleName {
Should Not Be $null
}
It 'Get-AzSAlert should be exported' {
Get-Command -Name Get-AzSAlert -ErrorAction SilentlyContinue |
It 'Get-AzsAlert should be exported' {
Get-Command -Name Get-AzsAlert -ErrorAction SilentlyContinue |
Should Not Be $null
}
}
@ -23,67 +23,56 @@ InModuleScope $script:ModuleName {
$HostComputer = $global:HostComputer
$ArmEndpoint = $global:ArmEndpoint
$natServer = $global:natServer
$AdminUser= $global:AdminUser
$AdminUser = $global:AdminUser
$AadServiceAdmin = $global:AadServiceAdmin
$AdminPassword = $global:AdminPassword
$AadServiceAdminPassword = $global:AadServiceAdminPassword
$stackLoginCreds = $global:AzureStackLoginCredentials
$VPNConnectionName = $global:VPNConnectionName
$AadTenant = $global:AadTenantID
$EnvironmentName = $global:EnvironmentName
Describe 'Infra - Functional Tests' {
It 'Get-AzSAlert should not throw' {
{ Get-AzSAlert -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsAlert should not throw' {
{ Get-AzsAlert } |
Should Not Throw
}
It 'Get-AzSScaleUnit should not throw' {
{ Get-AzSAlert -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsScaleUnit should not throw' {
{ Get-AzsAlert } |
Should Not Throw
}
It 'Get-AzSScaleUnitNode should not throw' {
{ Get-AzSScaleUnitNode -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsScaleUnitNode should not throw' {
{ Get-AzsScaleUnitNode } |
Should Not Throw
}
It 'Get-AzSStorageCapacity should not throw' {
{ Get-AzSStorageCapacity -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsStorageCapacity should not throw' {
{ Get-AzsStorageCapacity } |
Should Not Throw
}
It 'Get-AzSInfraRole should not throw' {
{ Get-AzSInfraRole -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsInfraRole should not throw' {
{ Get-AzsInfraRole } |
Should Not Throw
}
It 'Get-AzSInfraRoleInstance should not throw' {
{ Get-AzSInfraRoleInstance -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsInfraRoleInstance should not throw' {
{ Get-AzsInfraRoleInstance } |
Should Not Throw
}
It 'Get-AzSStorageShare should not throw' {
{ Get-AzSStorageShare -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsStorageShare should not throw' {
{ Get-AzsStorageShare } |
Should Not Throw
}
It 'Get-AzSlogicalnetwork should not throw' {
{ Get-AzSlogicalnetwork -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-Azslogicalnetwork should not throw' {
{ Get-Azslogicalnetwork } |
Should Not Throw
}
It 'Get-AzSUpdateSummary should not throw' {
{ Get-AzSUpdateSummary -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsUpdateSummary should not throw' {
{ Get-AzsUpdateSummary } |
Should Not Throw
}
It 'Get-AzSUpdate should not throw' {
{ Get-AzSUpdate -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds } |
It 'Get-AzsUpdate should not throw' {
{ Get-AzsUpdate } |
Should Not Throw
}
It 'Set-AzSLocationInformation should not throw' {
{ Set-AzSLocationInformation -TenantID $AadTenant -EnvironmentName $EnvironmentName -AzureStackCredentials $stackLoginCreds -Region 'local' -Latitude '12.972442' -Longitude '77.580643'} |
Should Not Throw
}
}

Двоичные данные
Marketplace/115.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 601 B

Двоичные данные
Marketplace/255.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Двоичные данные
Marketplace/40.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 260 B

Двоичные данные
Marketplace/533.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 220 KiB

Двоичные данные
Marketplace/90.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 662 B

Двоичные данные
Marketplace/Images/publish.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.0 KiB

Двоичные данные
Marketplace/Images/solution.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.7 KiB

Двоичные данные
Marketplace/Images/vmextension.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,16 @@
# Azure Stack Marketplace Toolkit parameter file
$ApplicationName = "Windows Server"
$Publisher = "Contoso"
$Summary = "Windows Server virtual machine"
$Description = "This marketplace item deploys a Windows Server virtual machine, a Virtual Network (with DNS), a Public IP address, a Network Security Group, and a Network Interface."
$Category = "Solutions"
$Icon40x40 = "C:\AzureStack_Marketplace\40.png"
$Icon90x90 = "C:\AzureStack_Marketplace\90.png"
$Icon115x115 = "C:\AzureStack_Marketplace\115.png"
$Icon255x115 = "C:\AzureStack_Marketplace\255.png"
$Screenshot533X324 = "C:\AzureStack_Marketplace\533.png"
$ArmTemplate = ""
$ExecutablePath = ""
$UserName = "admin@mydomain.onmicrosoft.com"
$Endpoint = "adminmanagement.local.azurestack.external"

72
Marketplace/README.md Normal file
Просмотреть файл

@ -0,0 +1,72 @@
# The Marketplace Toolkit for Microsoft Azure Stack
The Marketplace Toolkit for Microsoft Azure Stack provides service administrators and application developers with a UI to create and upload marketplace items to the Microsoft Azure Stack marketplace.
## Features
The toolkit allows you to
- Create and publish a solution for the marketplace. This accepts any main ARM template and allows you to define the tenant deployment experience, by creating steps, re-assigning and re-ordering parameters.
- Create and publish an extension for the marketplace. This creates a marketplace item for a VM Extension template that will surface on the extension tab of a deployed virtual machine.
- Publish an existing package. If you have an existing marketplace item package (.azpkg file), the publish wizard enables an easy wizard to publish the package to the marketplace.
## Requirements
To use the Marketplace Toolkit for Microsoft Azure Stack script you require:
- This script
- The gallerypackager executable (http://www.aka.ms/azurestackmarketplaceitem)
- Access as Azure Stack administrator to the Azure Stack environment. This is only required if you want to publish the generated package to the marketplace. For this you will also need to install the current PowerShell modules to support Azure Stack on the machine that runs this script (https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-powershell-install).
## Download the Marketplace Toolkit
To download the Azure Stack Marketplace Toolkit from this repository, run the following PowerShell script:
```PowerShell
# Variables
$Uri = 'https://raw.githubusercontent.com/Azure/AzureStack-Tools/master/Marketplace/'
$LocalPath = 'c:\AzureStack_Marketplace'
# Create folder
New-Item $LocalPath -Type directory
# Files
$files = @{
'40.png',
'90.png',
'115.png',
'255.png',
'533.png',
'MarketplaceToolkit.ps1',
'MarketplaceToolkit_parameters.ps1'
}
# Download files
$files | foreach { Invoke-WebRequest ($uri + $_) -OutFile ($LocalPath + '\' + $_) }
```
## Create a marketplace item
Start the Marketplace Toolkit in a PowerShell session.
``` PowerShell
cd c:\AzureStack_Marketplace
.\MarketplaceToolkit.ps1
```
From the dashboard you can select a solution, an extension or publish an existing .azpkg file. Select solution.
- Step one of the wizard will gather the text details for the marketplace item and the icons that will show up in the marketplace. Sample icons can be found in c:\AzureStack_Marketplace. Clicking preview UI Experience gives an idea of what the marketplace item will look like in Azure Stack. Optionally you can select a parameter file to populate the fields. This is useful when you want to reuse values for multiple marketplace items. c:\AzureStack_Marketplace contains an example parameter file called MarketplaceToolkit_parameters.ps1.
- Step two of the wizard specifies the ARM template for the marketplace item and the path of the gallerypackager executable. Browse for the ARM template. The deployment wizard tree view lists the parameters from the selected ARM. All parameters are listed on the basics step of the deployment wizard. You can add a new step by typing in the name of the step and click add. The new step is added to the tree view. If you select a parameter in the tree view the Details blade allows you to move the parameter up, down or move it to a different step. These changes are reflected in the tree view. You can only remove a step if there are no parameters assigned to it. The basics step cannot be removed. When the customization is finalized you can create the .azpkg file by selecting create (ensure you have specified the path to the gallerypackager.exe). The .azpkg file is generated and stored in the mydocuments folder. You can now close the wizard if you do not have access to an Azure Stack environment as Service Administrator or your Azure Stack environment is using ADFS for authentication.
- Step three of the wizard provides an job to publish the marketplace item just created, to the marketplace. Specify the Azure AD credentials for your Azure Stack environment. The Admin API endpoint needs to be configured as FQDN (e.g. adminmanagement.local.azurestack.external). Both the AzureAD username and the Admin API endpoint can be configured in the parameter file. When you click publish, a background job is started that will publish the .azpkg file to the Azure Stack Marketplace.
The VM extension on the dashboard is used to create a marketplace item for a VM Extension. This marketplace item will be visible in the Add extension tab on an existing VM in Azure Stack. The process to create an extension item is similar to a creating a solution, with the following exceptions:
- The category for an extension is not specified.
- The ARM template for an extension has two required parameters. vmName and Location. The UI will prevent you from selecting an ARM template if these two parameters are not present.
- You cannot specify additional deployment wizard steps. A VM extension consists of a single blade.
## Limitations
- The current version of the script only supports Azure AD for directly publishing an package to the marketplace. We are working on adding support for ADFS. When you are using ADFS you can still create the marketplace item package with the tool, but publishing the package to the marketplace is a manual process in PowerShell.
## Improvements
The Marketplace Toolkit for Microsoft Azure Stack is based on PowerShell and the Windows Presentation Foundation. It is published in this public repository so you can make improvements to it by submitting a pull request.

Просмотреть файл

@ -8,8 +8,8 @@
.SYNOPSIS
Produces Azure Resource Manager Policy document to apply to restrict Azure subscriptions to Azure Stack compatible functionality
#>
function Get-AzureStackRmPolicy
{
function Get-AzsPolicy {
$defaults = [System.IO.Path]::GetDirectoryName($PSCommandPath)
$providerMetadata = ConvertFrom-Json (Get-Content -Path ($defaults + "\AzureStack.Provider.Metadata.json") -Raw)
@ -18,10 +18,8 @@ function Get-AzureStackRmPolicy
$allowResources = @()
foreach ($p in $providerMetadata.value)
{
foreach ($r in $p.resourceTypes)
{
foreach ($p in $providerMetadata.value) {
foreach ($r in $p.resourceTypes) {
$allowResources += @{ field = "type"; equals = $p.namespace + "/" + $r.ResourceType}
$allowResources += @{ field = "type"; like = $p.namespace + "/" + $r.ResourceType + "/*" }
}
@ -31,7 +29,7 @@ function Get-AzureStackRmPolicy
$storageSkuField = "Microsoft.Storage/storageAccounts/sku.name"
$policy = @{
if = @{
if = @{
not = @{
allOf = @(
@{
@ -43,13 +41,13 @@ function Get-AzureStackRmPolicy
@{
allOf = @(
@{
field = $vmSkuField;
field = $vmSkuField;
exists = "true"
},
@{
not = @{
field = $vmSkuField;
in = $vmSkus
in = $vmSkus
}
}
)
@ -57,13 +55,13 @@ function Get-AzureStackRmPolicy
@{
allOf = @(
@{
field = $storageSkuField;
field = $storageSkuField;
exists = "true"
},
@{
not = @{
field = $storageSkuField;
in = $storageSkus
in = $storageSkus
}
}
)
@ -82,4 +80,4 @@ function Get-AzureStackRmPolicy
ConvertTo-Json $policy -Depth 100
}
Export-ModuleMember Get-AzureStackRmPolicy
Export-ModuleMember Get-AzsPolicy

Просмотреть файл

@ -11,7 +11,7 @@ Login-AzureRmAccount
$s = Select-AzureRmSubscription -SubscriptionName "<sub name>"
$subId = $s.Subscription.SubscriptionId
$policy = New-AzureRmPolicyDefinition -Name AzureStack -Policy (Get-AzureStackRmPolicy)
$policy = New-AzureRmPolicyDefinition -Name AzureStack -Policy (Get-AzsPolicy)
New-AzureRmPolicyAssignment -Name AzureStack -PolicyDefinition $policy -Scope /subscriptions/$subId
```
@ -25,7 +25,9 @@ New-AzureRmPolicyAssignment -Name AzureStack -PolicyDefinition $policy -Scope /s
```
To remove the Azure Stack policy, run this command with the same scope used when the policy was applied:
```powershell
Remove-AzureRmPolicyAssignment -Name AzureStack -Scope /subscriptions/$subId/resourceGroups/$rgName
Remove-AzureRmPolicyAssignment -Name AzureStack -Scope /subscriptions/$subId
```

Просмотреть файл

@ -1,13 +1,8 @@
# Azure Stack Technical Preview Version
These tools are meant for use with **Azure Stack Technical Preview 3 Refresh**. Azure Stack Technical Preview 3 (March build) users can still use the tools in the [TP3.N](https://github.com/Azure/AzureStack-Tools/tree/TP3.N).
These tools are meant for use with **Azure Stack Development Kit**. Azure Stack Technical Preview 3 Refresh users can still use the tools in the [TP3-Refresh](https://github.com/Azure/AzureStack-Tools/tree/TP3-Refresh).
A few notes for this release:
- Default ARM endpoints have changed in this release.
- Tools have been updated to include an EnvironmentName parameter.
- Make sure to use the the Net35 parameter when uploading a Server 2016 image for use with deploying the PaaS services
# Tools for using Azure and Azure Stack
## Tools for using Azure and Azure Stack
To use these tools, obtain Azure Stack compatible Azure PowerShell module. Unless you've installed from other sources, one way to do it is to obtain from public package repositories as follows. Note that both of these could still be used to operate against Azure as well as Azure Stack, but may lack some of the latest Azure features.
@ -16,12 +11,12 @@ For PowerShell, install the following:
```powershell
Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.9 -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.10 -Scope CurrentUser
```
Obtain the tools by cloning the git repository.
```
```commandline
git clone https://github.com/Azure/AzureStack-Tools.git --recursive
cd AzureStack-Tools
```
@ -33,44 +28,50 @@ invoke-webrequest https://github.com/Azure/AzureStack-Tools/archive/master.zip -
expand-archive master.zip -DestinationPath . -Force
cd AzureStack-Tools-master
```
Instructions below are relative to the root of the repo.
## [Azure Resource Manager policy for Azure Stack](Policy)
Constrains Azure subscription to the capabilities available in the Azure Stack.
- Apply Azure Stack policy to Azure subscriptions and resource groups
## [Deployment of Azure Stack](Deployment)
Helps prepare for Azure Stack deployment.
- Prepare to Deploy (boot from VHD)
- Prepare to Redeploy (boot back to original/base OS)
- Prepare to Deploy (boot from VHD)
- Prepare to Redeploy (boot back to original/base OS)
## [Connecting to Azure Stack](Connect)
Connect to an Azure Stack instance from your personal computer/laptop.
- Connect via VPN to an Azure Stack installation
- Configure Azure Stack PowerShell environment
- Prepare new subscriptions for use in PowerShell and CLI
## [Setting up Identity for Azure Stack](Identity)
Create and manage identity related objects and configurations for Azure Stack
- Create Service Principals in a disconnected topology
## [Azure Stack Service Administration](ServiceAdmin)
Manage plans and subscriptions in Azure Stack.
- Add default (unlimited) plans and quotas so that tenants can create new subscriptions
## [Azure Stack Compute Administration](ComputeAdmin)
Manage compute (VM) service in Azure Stack.
- Add VM Image to the Azure Stack Marketplace
## [Azure Stack Infrastructure Administration](Infrastructure)
Manage Azure Stack Infrastructure
- Get Infrastructure Roles
- Get Infrastructure Role Instances
- Start Infrastructure Role Instance
@ -97,6 +98,7 @@ Manage Azure Stack Infrastructure
## [AzureRM Template Validator](TemplateValidator)
Validate Azure ARM Template Capabilities
- resources - Types, Location, Apiversion
- Compute Capabilities - extensions, images, sizes
- Storage Capabilities - skus

Просмотреть файл

@ -1,10 +1,12 @@
# Registration
This script must be run from the Host machine. As a prerequisite, make sure that you have an Azure subscription and that you have installed Azure PowerShell:
```powershell
Install-Module -Name AzureRM
Install-Module -Name AzureRM
```
This script helps you to run through the steps of registering your Azure Stack with your Azure subscription. Additional details can be found in the [documentation](https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-register).
This script helps you to run through the steps of registering your Azure Stack with your Azure subscription. Additional details can be found in the [documentation](https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-register).
To run the script:
@ -12,4 +14,4 @@ To run the script:
RegisterWithAzure.ps1 -azureDirectory YourDirectory -azureSubscriptionId YourGUID -azureSubscriptionOwner YourAccountName
```
You will be prompted for your Azure credentials one more time as well as prompted to click "Enter" twice as the script runs.
You will be prompted for your Azure credentials one more time as well as prompted to click "Enter" twice as the script runs.

Просмотреть файл

@ -1,16 +1,16 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# See LICENSE.txt in the project root for license information.
# See LICENSE.txt in the project root for license information.
<#
.SYNOPSIS
This script can be used to register Azure Stack POC with Azure. To run this script, you must have a public Azure subscription of any type.
There must also be an account that is an owner or contributor of the subscription. This account cannot be an MSA (i.e. cannot be live.com or hotmail.com) or 2FA account.
<#
.DESCRIPTION
RegisterToAzure runs local scripts to connect your Azure Stack to Azure. After connecting with Azure, you can test marketplace syndication.
.SYNOPSIS
This script can be used to register Azure Stack POC with Azure. To run this script, you must have a public Azure subscription of any type.
There must also be an account that is an owner or contributor of the subscription.
.DESCRIPTION
RegisterToAzure runs local scripts to connect your Azure Stack to Azure. After connecting with Azure, you can test marketplace syndication.
The script will follow four steps:
Configure bridge identity: configures Azure Stack so that it can call to Azure via your Azure subscription
@ -18,176 +18,192 @@ Get registration request: get Azure Stack environment information to create a re
Register with Azure: uses Azure powershell to create an "Azure Stack Registration" resource on your Azure subscription
Activate Azure Stack: final step in connecting Azure Stack to be able to call out to Azure
.PARAMETER azureSubscriptionId
.PARAMETER azureSubscriptionId
Azure subscription ID that you want to register your Azure Stack with. This parameter is mandatory.
.PARAMETER azureDirectory
.PARAMETER azureDirectoryTenantName
Name of your AAD Tenant which your Azure subscription is a part of. This parameter is mandatory.
.PARAMETER azureSubscriptionOwner
.PARAMETER azureAccountId
Username for an owner/contributor of the azure subscription. This user must not be an MSA or 2FA account. This parameter is mandatory.
.PARAMETER azureSubscriptionPassword
.PARAMETER azureCredential
Password for the Azure subscription. You will be prompted to type in this password. This parameter is mandatory.
Powershell object that contains credential information such as user name and password. If not supplied script will request login via gui
.PARAMETER marketplaceSyndication
.PARAMETER azureEnvironment
Flag (ON/OFF) whether to enable downloading items from the Azure marketplace on this environment. Defaults to "ON".
Environment name for use in retrieving tenant details and running several of the activation scripts. Defaults to "AzureCloud".
.PARAMETER reportUsage
Flag (ON/OFF) whether to enable pushing usage data to Azure on this environment. Defaults to "ON".
.PARAMETER azureResourceManagerEndpoint
URI used for ActivateBridge.ps1 that refers to the endpoint for Azure Resource Manager. Defaults to "https://management.azure.com"
.EXAMPLE
This script must be run from the Host machine of the POC.
.\RegisterWithAzure.ps1 -azureSubscriptionId "5e0ae55d-0b7a-47a3-afbc-8b372650abd3" -azureDirectory "contoso.onmicrosoft.com" -azureSubscriptionOwner "serviceadmin@contoso.onmicrosoft.com"
This script must be run from the Host machine of the POC.
.\RegisterWithAzure.ps1 -azureSubscriptionId "5e0ae55d-0b7a-47a3-afbc-8b372650abd3" -azureDirectoryTenantName "contoso.onmicrosoft.com" -azureAccountId "serviceadmin@contoso.onmicrosoft.com"
.NOTES
Ensure that you have an Azure subscription
.NOTES
Ensure that you have an Azure subscription and it is registered for Microsoft.AzureStack namespace in Azure.
Namespace can be registered with the following command:
Register-AzureRmResourceProvider -ProviderNamespace 'microsoft.azurestack'
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]$azureDirectory,
param(
[Parameter(Mandatory = $false)]
[PSCredential] $azureCredential,
[Parameter(Mandatory = $true)]
[String]$azureSubscriptionId,
[String] $azureAccountId,
[Parameter(Mandatory = $true)]
[String]$azureSubscriptionOwner,
[String] $azureSubscriptionId,
[Parameter(Mandatory = $true)]
[securestring]$azureSubscriptionPassword,
[Parameter(Mandatory=$false)]
[ValidateSet('On', 'Off')]
[string] $marketplaceSyndication = 'On',
[String] $azureDirectoryTenantName,
[Parameter(Mandatory=$false)]
[ValidateSet('On', 'Off')]
[string] $reportUsage = 'On'
[Parameter(Mandatory = $false)]
[String] $azureEnvironment = "AzureCloud",
[Parameter(Mandatory = $false)]
[String] $azureResourceManagerEndpoint = "https://management.azure.com",
[Parameter(Mandatory = $false)]
[bool] $enableSyndication = $true,
[Parameter(Mandatory = $false)]
[Switch] $reportUsage = $false
)
#requires -Module AzureRM.Profile
#requires -Module AzureRM.Resources
#requires -RunAsAdministrator
Import-Module C:\CloudDeployment\ECEngine\EnterpriseCloudEngine.psm1 -Force
cd C:\CloudDeployment\Setup\Activation\Bridge
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
$VerbosePreference = [System.Management.Automation.ActionPreference]::Continue
Read-Host "This script will turn marketplace syndication $marketplaceSyndication and usage reporting $reportUsage. You can change this by running the script using different flags. Press Enter to continue."
Import-Module C:\CloudDeployment\ECEngine\EnterpriseCloudEngine.psd1 -Force
Set-Location C:\CloudDeployment\Setup\Activation\Bridge
# Determine version of TP3 and set values accordingly
$versionInfo = [xml] (Get-Content -Path C:\CloudDeployment\Configuration\Version\version.xml)
if($versionInfo.Version -ge "1.0.170308.2")
{
Write-Verbose -Message "Using TP3.N release" -Verbose
$bridgeAppConfigFile = "\\SU1FileServer\SU1_Infrastructure_1\ASResourceProvider\Config\AzureBridge.IdentityApplication.Configuration.json"
}
elseif($versionInfo.Version -eq "1.0.170225.2")
{
Write-Verbose -Message "Using TP3.O release" -Verbose
$bridgeAppConfigFile = "\\SU1FileServer\SU1_Infrastructure_1\ASResourceProvider\Config\ConnectionAzureArm.IdentityApplication.Configuration.json"
}
else
{
Write-Error -Message "Unsupported TP3 release" -Verbose
}
#
# Pre-req: Version check
#
$versionInfo = [xml] (Get-Content -Path C:\CloudDeployment\Configuration\Version\version.xml)
$minVersion = "1.0.170501.1"
if ($versionInfo.Version -lt $minVersion) {
Write-Error -Message "Script only applicable for Azure Stack builds $minVersion or later"
}
else {
Write-Verbose -Message "Running registration on build $($versionInfo.Version)" -Verbose
}
#
# Obtain refresh token for Azure identity
#
Import-Module C:\CloudDeployment\Setup\Common\AzureADConfiguration.psm1 -ErrorAction Stop
$AzureDirectoryTenantId = Get-TenantIdFromName -azureEnvironment $azureEnvironment -tenantName $azureDirectoryTenantName
if (-not $azureCredential) {
Write-Verbose "Prompt user to enter Azure Credentials to get refresh token"
$tenantDetails = Get-AzureADTenantDetails -AzureEnvironment $azureEnvironment -AADDirectoryTenantName $azureDirectoryTenantName
}
else {
Write-Verbose "Using provided Azure Credentials to get refresh token"
$tenantDetails = Get-AzureADTenantDetails -AzureEnvironment $azureEnvironment -AADDirectoryTenantName $azureDirectoryTenantName -AADAdminCredential $azureCredential
}
$refreshToken = (ConvertTo-SecureString -string $tenantDetails["RefreshToken"] -AsPlainText -Force)
#
# Step 1: Configure Bridge identity
#
$azureCreds = New-Object System.Management.Automation.PSCredential($azureSubscriptionOwner, $azureSubscriptionPassword)
.\Configure-BridgeIdentity.ps1 -AzureCredential $azureCreds -AzureDirectoryTenantId $azureDirectory -AzureEnvironment AzureCloud -Verbose
Write-Host "STEP 1: Configure local identity completed"
Write-Verbose "Calling Configure-BridgeIdentity.ps1"
.\Configure-BridgeIdentity.ps1 -RefreshToken $refreshToken -AzureAccountId $azureAccountId -AzureDirectoryTenantName $azureDirectoryTenantName -AzureEnvironment $azureEnvironment -Verbose
Write-Verbose "Configure Bridge identity completed"
#
# Step 2: Create new registration request
#
$bridgeAppConfigFile = "\\SU1FileServer\SU1_Infrastructure_1\ASResourceProvider\Config\AzureBridge.IdentityApplication.Configuration.json"
$registrationOutputFile = "c:\temp\registration.json"
Write-Verbose "Calling New-RegistrationRequest.ps1"
.\New-RegistrationRequest.ps1 -BridgeAppConfigFile $bridgeAppConfigFile -RegistrationRequestOutputFile $registrationOutputFile -Verbose
Read-Host "STEP 2: Registration request completed. Re-enter your Azure subscription credentials in the next step. Note: Step 3 can be run from a different machine that is connected to Azure. Press Enter to continue and run step 3 from this machine."
Write-Verbose "New registration request completed"
#
# Step 3: Register Azure Stack with Azure
#
New-Item -ItemType Directory -Force -Path "C:\temp"
$registrationRequestFile = "c:\temp\registration.json"
$registrationOutputFile = "c:\temp\registrationOutput.json"
Login-AzureRmAccount -EnvironmentName AzureCloud
Select-AzureRmSubscription -SubscriptionId $azureSubscriptionId
$timestamp = [DateTime]::Now.ToString("yyyyMMdd-HHmmss")
$logPath = (New-Item -Path "$env:SystemDrive\CloudDeployment\Logs\" -ItemType Directory -Force).FullName
$logFile = Join-Path -Path $logPath -ChildPath "Register-AzureStack.${timestamp}.txt"
try { Start-Transcript -Path $logFile -Force | Out-String | Write-Verbose -Verbose } catch { Write-Warning -Message $_.Exception.Message }
# Ensure subscription is registered to Microsoft.AzureStack namespace in Azure
Register-AzureRmResourceProvider -ProviderNamespace 'microsoft.azurestack'
$result = $null
$attempts = 0
$maxAttempts = 20
$delayInSecondsBetweenAttempts = 10
do
{
$attempts++
Write-Verbose "[CHECK] Checking for resource provider registration... (attempt $attempts of $maxAttempts)"
$result = $(Get-AzureRmResourceProvider -ProviderNamespace 'microsoft.azurestack')[0].RegistrationState -EQ 'Registered'
$result
if ((-not $result) -and ($attempts -lt $maxAttempts))
{
Write-Verbose "[DELAY] Attempt $attempts failed to see provider registration, delaying for $delayInSecondsBetweenAttempts seconds before retry"
Start-Sleep -Seconds $delayInSecondsBetweenAttempts
}
}
while ((-not $result) -and ($attempts -lt $maxAttempts))
Write-Verbose "Calling Register-AzureStack.ps1"
.\Register-AzureStack.ps1 -BillingModel PayAsYouUse -EnableSyndication -ReportUsage -SubscriptionId $azureSubscriptionId -AzureAdTenantId $AzureDirectoryTenantId `
-RefreshToken $refreshToken -AzureAccountId $azureAccountId -AzureEnvironmentName $azureEnvironment -RegistrationRequestFile $registrationRequestFile `
-RegistrationOutputFile $registrationOutputFile -Location "westcentralus" -Verbose
Write-Verbose "Register Azure Stack with Azure completed"
if (-not $result)
{
throw New-Object System.InvalidOperationException("Azure Bridge Resource Provider was registered but did not become routable within the alloted time")
try { Stop-Transcript -Verbose } catch { Write-Warning "$_" }
#
# workaround to enable syndication and usage
#
$activationDataFile = "c:\temp\regOutput2.json"
$reg = Get-Content $registrationOutputFile | ConvertFrom-Json
$newProps = @{
ObjectId = $reg.properties.ObjectId
ProvisioningState = $reg.properties.provisioningState
enablesyndication = $enableSyndication
reportusage = $reportUsage
}
.\Register-AzureStack.ps1 -BillingModel Consumption -Syndication $marketplaceSyndication -ReportUsage $reportUsage -SubscriptionId $azureSubscriptionId -AzureAdTenantId $azureDirectory `
-AzureCredential $azureCreds -AzureEnvironmentName AzureCloud -RegistrationRequestFile $registrationRequestFile -RegistrationOutputFile $registrationOutputFile -Location "westcentralus" -Verbose
Read-Host "STEP 3: Register Azure Stack with Azure completed. Press Enter to continue."
$reg.properties = $newProps
$reg | ConvertTo-Json -Depth 4 | Out-File -FilePath $activationDataFile
Write-Verbose "Activation file is at : $activationDataFile"
#
# Step 4: Activate Azure Stack
#
$regResponse = Get-Content -path $activationDataFile
$bytes = [System.Text.Encoding]::UTF8.GetBytes($regResponse)
$activationCode = [Convert]::ToBase64String($bytes)
# temporary step to adjust registration output to expected format
$reg = Get-Content $registrationOutputFile | ConvertFrom-Json
$newProps = @{
ObjectId = $reg.properties.ObjectId
ProvisioningState = $reg.properties.provisioningState
syndication = $marketplaceSyndication
usagebridge = $reportUsage
try {
.\Activate-Bridge.ps1 -activationCode $activationCode -AzureResourceManagerEndpoint $azureResourceManagerEndpoint -Verbose
}
$reg.properties = $newProps
$reg | ConvertTo-Json -Depth 4 | Out-File -FilePath $registrationOutputFile
catch {
$exceptionMessage = $_.Exception.Message
$regResponse = Get-Content -path $registrationOutputFile
$AzureResourceManagerEndpoint = "https://management.azure.com"
if($versionInfo.Version -ge "1.0.170308.2")
{
$bytes = [System.Text.Encoding]::UTF8.GetBytes($regResponse)
$activationCode = [Convert]::ToBase64String($bytes)
.\Activate-Bridge.ps1 -activationCode $activationCode -AzureResourceManagerEndpoint $AzureResourceManagerEndpoint -Verbose
if($exceptionMessage.Contains("Application is currently being upgraded"))
{
Write-Warning "Activate-Bridge: Known issue with redundant service fabric upgrade call"
}
else
{
Write-Error -Message "Activate-Bridge: Error : $($_.Exception)"
}
}
elseif($versionInfo.Version -eq "1.0.170225.2")
{
$bytes = [System.Text.Encoding]::Unicode.GetBytes($regResponse)
$activationCode = [Convert]::ToBase64String($bytes)
.\Activate-Bridge.ps1 -activationCode $activationCode -Verbose
}
Write-Host "STEP 4: Activate Azure Stack completed"
Write-Host "Registration complete. Close and re-open the Marketplace Management blade in the admin portal."
Write-Verbose "Azure Stack activation completed"

Просмотреть файл

@ -2,239 +2,159 @@
# See LICENSE.txt in the project root for license information.
#requires -Version 4.0
#requires -Modules AzureStack.Connect
<#
.SYNOPSIS
Creates "default" tenant offer with unlimited quotas across Compute, Network, Storage and KeyVault services.
#>
function New-AzSTenantOfferAndQuotas
{
param (
[parameter(HelpMessage="Name of the offer to be made advailable to tenants")]
[string] $Name ="default",
[parameter(HelpMessage="Azure Stack region in which to define plans and quotas")]
[string]$Location = "local",
[Parameter(HelpMessage="If this parameter is not specified all quotas are assigned. Provide a sub selection of quotas in this parameter if you do not want all quotas assigned.")]
[ValidateSet('Compute','Network','Storage','KeyVault','Subscriptions',IgnoreCase =$true)]
[array]$ServiceQuotas,
[parameter(Mandatory=$true,HelpMessage="The name of the AzureStack environment")]
[string] $EnvironmentName,
[parameter(Mandatory=$true,HelpMessage="Azure Stack service administrator credential")]
[pscredential] $azureStackCredentials,
[parameter(mandatory=$true, HelpMessage="TenantID of Identity Tenant")]
[string] $tenantID
)
$azureStackEnvironment = Get-AzureRmEnvironment -Name $EnvironmentName -ErrorAction SilentlyContinue
if($azureStackEnvironment -ne $null) {
$ARMEndpoint = $azureStackEnvironment.ResourceManagerUrl
}
else {
Write-Error "The Azure Stack Admin environment with the name $EnvironmentName does not exist. Create one with Add-AzureStackAzureRmEnvironment." -ErrorAction Stop
}
Write-Verbose "Obtaining token from AAD..." -Verbose
$subscription, $headers = (Get-AzureStackAdminSubTokenHeader -TenantId $tenantId -AzureStackCredentials $azureStackCredentials -EnvironmentName $EnvironmentName)
Write-Verbose "Creating quotas..." -Verbose
$Quotas = @()
if ((!($ServiceQuotas)) -or ($ServiceQuotas -match 'Compute')){ $Quotas += New-ComputeQuota -AdminUri $armEndPoint -SubscriptionId $subscription -AzureStackTokenHeader $headers -ArmLocation $Location }
if ((!($ServiceQuotas)) -or ($ServiceQuotas -match 'Network')){ $Quotas += New-NetworkQuota -AdminUri $armEndPoint -SubscriptionId $subscription -AzureStackTokenHeader $headers -ArmLocation $Location }
if ((!($ServiceQuotas)) -or ($ServiceQuotas -match 'Storage')){ $Quotas += New-StorageQuota -AdminUri $armEndPoint -SubscriptionId $subscription -AzureStackTokenHeader $headers -ArmLocation $Location }
if ((!($ServiceQuotas)) -or ($ServiceQuotas -match 'KeyVault')){ $Quotas += Get-KeyVaultQuota -AdminUri $armEndPoint -SubscriptionId $subscription -AzureStackTokenHeader $headers -ArmLocation $Location }
if ((!($ServiceQuotas)) -or ($ServiceQuotas -match 'Subscriptions')){ $Quotas += Get-SubscriptionsQuota -AdminUri $armEndpoint -SubscriptionId $subscription -AzureStackTokenHeader $headers -ArmLocation $Location }
Write-Verbose "Creating resource group for plans and offers..." -Verbose
if (Get-AzureRmResourceGroup -Name $Name -ErrorAction SilentlyContinue)
{
Remove-AzureRmResourceGroup -Name $Name -Force -ErrorAction Stop
}
New-AzureRmResourceGroup -Name $Name -Location $Location -ErrorAction Stop
Write-Verbose "Creating plan..." -Verbose
$plan = New-AzureRMPlan -Name $Name -DisplayName $Name -ArmLocation $Location -ResourceGroup $Name -QuotaIds $Quotas
Write-Verbose "Creating public offer..." -Verbose
$offer = New-AzureRMOffer -Name $Name -DisplayName $Name -State Public -BasePlanIds @($plan.Id) -ArmLocation $Location -ResourceGroup $Name
return $offer
}
Export-ModuleMember New-AzSTenantOfferAndQuotas
function Get-SubscriptionsQuota
{
function Add-AzsStorageQuota {
param(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $AdminUri,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $SubscriptionId,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[hashtable] $AzureStackTokenHeader,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $ArmLocation
)
$getSubscriptionsQuota = @{
Uri = "{0}/subscriptions/{1}/providers/Microsoft.Subscriptions.Admin/locations/{2}/quotas?api-version=2015-11-01" -f $AdminUri, $SubscriptionId, $ArmLocation
Method = "GET"
Headers = $AzureStackTokenHeader
ContentType = "application/json"
}
$subscriptionsQuota = Invoke-RestMethod @getSubscriptionsQuota
$subscriptionsQuota.value.Id
}
function New-StorageQuota
{
param(
[string] $Name ="default",
[string] $Name = "default",
[int] $CapacityInGb = 1000,
[int] $NumberOfStorageAccounts = 2000,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $AdminUri,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $SubscriptionId,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[hashtable] $AzureStackTokenHeader,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $ArmLocation
)
[string] $Location = $null
)
$Location = Get-AzsHomeLocation -Location $Location
$ApiVersion = "2015-12-01-preview"
$uri = "{0}/subscriptions/{1}/providers/Microsoft.Storage.Admin/locations/{2}/quotas/{3}?api-version={4}" -f $AdminUri, $SubscriptionId, $ArmLocation, $Name, $ApiVersion
$RequestBody = @"
{
"name":"$Name",
"location":"$ArmLocation",
"properties": {
"capacityInGb": $CapacityInGb,
"numberOfStorageAccounts": $NumberOfStorageAccounts
$params = @{
ResourceName = "{0}/{1}" -f $Location, $Name
ResourceType = "Microsoft.Storage.Admin/locations/quotas"
ApiVersion = "2015-12-01-preview"
Properties = @{
capacityInGb = $CapacityInGb
numberOfStorageAccounts = $NumberOfStorageAccounts
}
}
"@
$storageQuota = Invoke-RestMethod -Method Put -Uri $uri -Body $RequestBody -ContentType 'application/json' -Headers $AzureStackTokenHeader
$storageQuota.Id
New-AzsServiceQuota @params
}
function New-ComputeQuota
{
function Add-AzsComputeQuota {
param(
[string] $Name ="default",
[string] $Name = "default",
[int] $VmCount = 1000,
[int] $MemoryLimitMB = 1048576,
[int] $CoresLimit = 1000,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $AdminUri,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $SubscriptionId,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[hashtable] $AzureStackTokenHeader,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $ArmLocation
)
[string] $Location = $null
)
$ApiVersion = "2015-12-01-preview"
$uri = "{0}/subscriptions/{1}/providers/Microsoft.Compute.Admin/locations/{2}/quotas/{3}?api-version={4}" -f $AdminUri, $SubscriptionId, $ArmLocation, $Name, $ApiVersion
$RequestBody = @"
{
"name":"$Name",
"type":"Microsoft.Compute.Admin/quotas",
"location":"$ArmLocation",
"properties":{
"virtualMachineCount":$VmCount,
"memoryLimitMB":$MemoryLimitMB,
"coresLimit":$CoresLimit
$Location = Get-AzsHomeLocation -Location $Location
$params = @{
ResourceName = "{0}/{1}" -f $Location, $Name
ResourceType = "Microsoft.Compute.Admin/locations/quotas"
ApiVersion = "2015-12-01-preview"
Properties = @{
virtualMachineCount = $VmCount
memoryLimitMB = $MemoryLimitMB
coresLimit = $CoresLimit
}
}
"@
$computeQuota = Invoke-RestMethod -Method Put -Uri $uri -Body $RequestBody -ContentType 'application/json' -Headers $AzureStackTokenHeader
$computeQuota.Id
New-AzsServiceQuota @params
}
function New-NetworkQuota
{
function Add-AzsNetworkQuota {
param(
[string] $Name ="default",
[int] $PublicIpsPerSubscription = 500,
[int] $VNetsPerSubscription = 500,
[int] $GatewaysPerSubscription = 10,
[int] $ConnectionsPerSubscription = 20,
[int] $LoadBalancersPerSubscription = 500,
[int] $NicsPerSubscription = 1000,
[int] $SecurityGroupsPerSubscription = 500,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $AdminUri,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $SubscriptionId,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[hashtable] $AzureStackTokenHeader,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $ArmLocation
[string] $Name = "default",
[int] $PublicIpsPerSubscription = 500,
[int] $VNetsPerSubscription = 500,
[int] $GatewaysPerSubscription = 10,
[int] $ConnectionsPerSubscription = 20,
[int] $LoadBalancersPerSubscription = 500,
[int] $NicsPerSubscription = 1000,
[int] $SecurityGroupsPerSubscription = 500,
[string] $Location = $null
)
$ApiVersion = "2015-06-15"
$uri = "{0}/subscriptions/{1}/providers/Microsoft.Network.Admin/locations/{2}/quotas/{3}?api-version={4}" -f $AdminUri, $SubscriptionId, $ArmLocation, $Name, $ApiVersion
$id = "/subscriptions/{0}/providers/Microsoft.Network.Admin/locations/{1}/quotas/{2}" -f $SubscriptionId, $ArmLocation, $quotaName
$RequestBody = @"
{
"id":"$id",
"name":"$Name",
"type":"Microsoft.Network.Admin/quotas",
"location":"$ArmLocation",
"properties":{
"maxPublicIpsPerSubscription":$PublicIpsPerSubscription,
"maxVnetsPerSubscription":$VNetsPerSubscription,
"maxVirtualNetworkGatewaysPerSubscription":$GatewaysPerSubscription,
"maxVirtualNetworkGatewayConnectionsPerSubscription":$ConnectionsPerSubscription,
"maxLoadBalancersPerSubscription":$LoadBalancersPerSubscription,
"maxNicsPerSubscription":$NicsPerSubscription,
"maxSecurityGroupsPerSubscription":$SecurityGroupsPerSubscription,
$Location = Get-AzsHomeLocation -Location $Location
$params = @{
ResourceName = "{0}/{1}" -f $Location, $Name
ResourceType = "Microsoft.Network.Admin/locations/quotas"
ApiVersion = "2015-06-15"
Properties = @{
maxPublicIpsPerSubscription = $PublicIpsPerSubscription
maxVnetsPerSubscription = $VNetsPerSubscription
maxVirtualNetworkGatewaysPerSubscription = $GatewaysPerSubscription
maxVirtualNetworkGatewayConnectionsPerSubscription = $ConnectionsPerSubscription
maxLoadBalancersPerSubscription = $LoadBalancersPerSubscription
maxNicsPerSubscription = $NicsPerSubscription
maxSecurityGroupsPerSubscription = $SecurityGroupsPerSubscription
}
}
"@
$networkQuota = Invoke-RestMethod -Method Put -Uri $uri -Body $RequestBody -ContentType 'application/json' -Headers $AzureStackTokenHeader
$networkQuota.Id
New-AzsServiceQuota @params
}
function Get-KeyVaultQuota
{
function Get-AzsSubscriptionsQuota {
param(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $AdminUri,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $SubscriptionId,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[hashtable] $AzureStackTokenHeader,
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $ArmLocation
)
[string] $Location
)
$uri = "{0}/subscriptions/{1}/providers/Microsoft.Keyvault.Admin/locations/{2}/quotas?api-version=2014-04-01-preview" -f $AdminUri, $SubscriptionId, $ArmLocation
$kvQuota = Invoke-RestMethod -Method Get -Uri $uri -Headers $AzureStackTokenHeader -ContentType 'application/json'
$kvQuota.Value.Id
$Location = Get-AzsHomeLocation -Location $Location
$params = @{
ResourceName = $Location
ResourceType = "Microsoft.Subscriptions.Admin/locations/quotas"
ApiVersion = "2015-11-01"
}
Get-AzsServiceQuota @params
}
function Get-AzsKeyVaultQuota {
param(
[string] $Location
)
$Location = Get-AzsHomeLocation -Location $Location
$params = @{
ResourceName = $Location
ResourceType = "Microsoft.Keyvault.Admin/locations/quotas"
ApiVersion = "2014-04-01-preview"
}
Get-AzsServiceQuota @params
}
function Get-AzsHomeLocation {
param(
[string] $Location
)
if ($Location) {
return $Location
}
$locationResource = Get-AzsLocation
return $locationResource.Name
}
function New-AzsServiceQuota {
param(
[string] $ResourceName,
[string] $ResourceType,
[string] $ApiVersion,
[PSObject] $Properties
)
$serviceQuota = New-AzureRmResource -ResourceName $ResourceName -ResourceType $ResourceType -ApiVersion $ApiVersion -Properties $Properties -Force
$serviceQuota.ResourceId
}
function Get-AzsServiceQuota {
param(
[string] $ResourceName,
[string] $ResourceType,
[string] $ApiVersion
)
$serviceQuota = Get-AzureRmResource -ResourceName $ResourceName -ApiVersion $ApiVersion -ResourceType $ResourceType
$serviceQuota.ResourceId
}

Просмотреть файл

@ -9,35 +9,25 @@ Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.9 -Scope CurrentUser
```
Then make sure the following modules are imported:
```powershell
Import-Module ..\Connect\AzureStack.Connect.psm1
Import-Module .\AzureStack.ServiceAdmin.psm1
```
You will need to reference your Azure Stack Administrator environment. To create an administrator environment use the below. The ARM endpoint below is the administrator default for a one-node environment.
```powershell
Add-AzureStackAzureRmEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
Add-AzsEnvironment -Name "AzureStackAdmin" -ArmEndpoint "https://adminmanagement.local.azurestack.external"
```
Creating quotas/offers/plans requires that you obtain the value of your Directory Tenant ID. For **Azure Active Directory** environments provide your directory tenant name:
```powershell
$TenantID = Get-DirectoryTenantID -AADTenantName "<mydirectorytenant>.onmicrosoft.com" -EnvironmentName AzureStackAdmin
```
For **ADFS** environments use the following:
```powershell
$TenantID = Get-DirectoryTenantID -ADFS -EnvironmentName AzureStackAdmin
```
## Create default plan and quota for tenants
```powershell
New-AzSTenantOfferAndQuotas -tenantID $TenantID -EnvironmentName "AzureStackAdmin"
Add-AzsTenantOfferAndQuota
```
Tenants can now see the "default" offer available to them and can subscribe to it. The offer includes unlimited compute, network, storage and key vault usage.
Tenants can now see the "default" offer available to them and can subscribe to it. The offer includes unlimited compute, network, storage and key vault usage.

Просмотреть файл

@ -10,38 +10,12 @@ Describe $script:ModuleName {
Get-Module -Name $script:ModuleName |
Should Not Be $null
}
It 'New-AzSTenantOfferAndQuotas should be exported' {
Get-Command -Name New-AzSTenantOfferAndQuotas -ErrorAction SilentlyContinue |
Should Not Be $null
}
}
}
InModuleScope $script:ModuleName {
$HostComputer = $global:HostComputer
$ArmEndpoint = $global:ArmEndpoint
$natServer = $global:natServer
$AdminUser= $global:AdminUser
$AadServiceAdmin = $global:AadServiceAdmin
$AdminPassword = $global:AdminPassword
$AadServiceAdminPassword = $global:AadServiceAdminPassword
$stackLoginCreds = $global:AzureStackLoginCredentials
$VPNConnectionName = $global:VPNConnectionName
$AadTenant = $global:AadTenantID
$EnvironmentName = $global:EnvironmentName
Describe 'ServiceAdmin - Functional Tests' {
It 'New-AzSTenantOfferAndQuotas should create Quotas, Plan and Offer' {
{ New-AzSTenantOfferAndQuotas -tenantID $AadTenant -AzureStackCredentials $stackLoginCreds -EnvironmentName $EnvironmentName } |
Should Not Throw
}
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,28 +1,37 @@
# Validate Azure ARM Template Capabilities
Instructions below are relative to the .\TemplateValidator folder of the [AzureStack-Tools repo](..).
To Validate Compute Capabilities such as Images, Extensions & Sizes available in the CloudCapabilities.json add -IncludeComputeCapabilities
To Validate Storage Capabilities such as Skus available in the CloudCapabilities.json add -IncludeStorageCapabilities
```powershell
Import-Module ".\AzureRM.TemplateValidator.psm1"
```
# Prerequisites
## Prerequisites
Create CloudCapabilities.json by using Get-AzureRMCloudCapabilities tool [AzureStack-Tools repo/CloudCapabilities](../CloudCapabilities). or use the provided sample AzureStackCapabilities_TP3.json in this folder
For Azure/AzureStack quickstart templates, git clone from below links
https://github.com/Azure/AzureStack-QuickStart-Templates/
https://github.com/Azure/Azure-QuickStart-Templates/
# Usage
`https://github.com/Azure/AzureStack-QuickStart-Templates/`
`https://github.com/Azure/Azure-QuickStart-Templates/`
## Usage
```powershell
$TemplatePath = "<Provide Template(s) Path>"
$CapabilitiesPath = ".\AzureStackCapabilities_TP3.json"
Test-AzureRMTemplate -TemplatePath $TemplatePath -CapabilitiesPath $CapabilitiesPath -Verbose #-IncludeComputeCapabilities -IncludeStorageCapabilities
```
#Reporting Usage
Passed - Validation passed. The template has all the Capabilities to deploy on the validated Cloud
## Reporting Usage
Passed - Validation passed. The template has all the Capabilities to deploy on the validated Cloud
NotSupported - The template Capabilities is currently not supported on the validated cloud
Exception - Exception in processing and validating the template
Recommend - The template has all the Capabilities to deploy on the validated Cloud but has recommendations for best practices
Warning - Changes are required either in Template or the validated cloud to deploy succesfully
# TroubleShooting
## TroubleShooting
For "NotSupported" - Refer the region specific capability JSON for the supported capabilities.
For Warnings(in Console Output) such as "No StorageSkus found in region specific Capabilities JSON file.", Please run Get-AzureRMCloudCapabilities with -IncludeComputeCapabilities and -IncludeStorageCapabilities

Просмотреть файл

@ -1,19 +1,19 @@
param (
[parameter(mandatory=$true, HelpMessage="Azure Stack One Node host address or name such as '1.2.3.4'")]
[parameter(mandatory = $true, HelpMessage = "Azure Stack One Node host address or name such as '1.2.3.4'")]
[string] $HostComputer,
[Parameter(mandatory=$true, HelpMessage="The Admin ARM endpoint of the Azure Stack Environment")]
[Parameter(mandatory = $true, HelpMessage = "The Admin ARM endpoint of the Azure Stack Environment")]
[string] $ArmEndpoint,
[parameter(HelpMessage="NAT computer name in this Azure Stack Instance")]
[string] $natServer = "MAS-BGPNAT01",
[parameter(HelpMessage="Administrator user name of this Azure Stack Instance")]
[parameter(HelpMessage = "NAT computer name in this Azure Stack Instance")]
[string] $natServer = "Azs-BGPNAT01",
[parameter(HelpMessage = "Administrator user name of this Azure Stack Instance")]
[string] $AdminUser = "administrator",
[parameter(HelpMessage="Administrator Azure Stack Environment Name")]
[parameter(HelpMessage = "Administrator Azure Stack Environment Name")]
[string] $EnvironmentName = "AzureStackAdmin",
[parameter(mandatory=$true, HelpMessage="Administrator password used to deploy this Azure Stack instance")]
[parameter(mandatory = $true, HelpMessage = "Administrator password used to deploy this Azure Stack instance")]
[securestring] $AdminPassword,
[parameter(mandatory=$true, HelpMessage="The AAD service admin user name of this Azure Stack Instance")]
[parameter(mandatory = $true, HelpMessage = "The AAD service admin user name of this Azure Stack Instance")]
[string] $AzureStackServiceAdmin,
[parameter(mandatory=$true, HelpMessage="AAD Service Admin password used to deploy this Azure Stack instance")]
[parameter(mandatory = $true, HelpMessage = "AAD Service Admin password used to deploy this Azure Stack instance")]
[securestring] $AzureStackServiceAdminPassword
)
@ -27,7 +27,7 @@ $global:AzureStackServiceAdmin = $AzureStackServiceAdmin
$global:AzureStackServiceAdminPassword = $AzureStackServiceAdminPassword
$global:EnvironmentName = $EnvironmentName
$ServiceAdminCreds = New-Object System.Management.Automation.PSCredential "$global:AzureStackServiceAdmin", ($global:AzureStackServiceAdminPassword)
$ServiceAdminCreds = New-Object System.Management.Automation.PSCredential "$global:AzureStackServiceAdmin", ($global:AzureStackServiceAdminPassword)
$global:AzureStackLoginCredentials = $ServiceAdminCreds
$global:VPNConnectionName = "AzureStackTestVPN"

Просмотреть файл

@ -1,3 +1,5 @@
# PreReqs
As a prerequisite, make sure that you installed the correct PowerShell modules and versions:
```powershell
@ -5,7 +7,6 @@ Install-Module -Name 'AzureRm.Bootstrapper' -Scope CurrentUser
Install-AzureRmProfile -profile '2017-03-09-profile' -Force -Scope CurrentUser
Install-Module -Name AzureStack -RequiredVersion 1.2.9 -Scope CurrentUser
```
```
Use this script to extract usage data from the AzureStack Usage API's and export it to a CSV file
For more information on Billing and Usage see [here](https://docs.microsoft.com/en-us/azure/azure-stack/azure-stack-billing-and-chargeback)
```

Просмотреть файл

@ -1,26 +1,22 @@
<#
<#
.Synopsis
Exports usage meters from Azure Stack to a csv file
.DESCRIPTION
Long description
.EXAMPLE
Export-AzureStackUsageDetails -StartTime 2/15/2017 -EndTime 2/16/2017 -AzureStackDomain azurestack.local -AADDomain mydir.onmicrosoft.com -Granularity Hourly
Export-AzsUsage -StartTime 2/15/2017 -EndTime 2/16/2017 -Granularity Hourly
#>
function Export-AzureStackUsage {
function Export-AzsUsage {
Param
(
[Parameter(Mandatory = $true)]
[datetime]
$StartTime,
[Parameter(Mandatory = $true)]
[datetime]
$EndTime ,
[Parameter(Mandatory = $true)]
[String]
$AzureStackDomain ,
[Parameter(Mandatory = $true)]
[String]
$AADDomain ,
[Parameter(Mandatory = $false)]
[ValidateSet("Hourly", "Daily")]
[String]
@ -29,15 +25,9 @@ function Export-AzureStackUsage {
[String]
$CsvFile = "UsageSummary.csv",
[Parameter (Mandatory = $false)]
[PSCredential]
$Credential,
[Parameter(Mandatory = $false)]
[Switch]
$TenantUsage,
[Parameter(Mandatory = $false)]
[String]
$Subscription,
[Parameter(Mandatory = $false)]
[Switch]
$Force
)
@ -66,115 +56,80 @@ function Export-AzureStackUsage {
}
#Output Files
if (Test-Path -Path $CsvFile -ErrorAction SilentlyContinue) {
if ($Force) {
if (Test-Path -Path $CsvFile -ErrorAction SilentlyContinue)
{
if ($Force)
{
Remove-Item -Path $CsvFile -Force
}
else {
Write-Host "$CsvFile alreday exists use -Force to overwrite"
Write-Error "'$CsvFile' already exists use -Force to overwrite"
return
}
}
New-Item -Path $CsvFile -ItemType File | Out-Null
#get auth metadata and acquire token for REST call
$api = 'adminmanagement'
if ($TenantUsage) {
$api = 'management'
}
$uri = 'https://{0}.{1}/metadata/endpoints?api-version=1.0' -f $api, $AzureStackDomain
$endpoints = (Invoke-RestMethod -Uri $uri -Method Get)
$activeDirectoryServiceEndpointResourceId = $endpoints.authentication.audiences[0]
$loginEndpoint = $endpoints.authentication.loginEndpoint
$authority = $loginEndpoint + $AADDomain + '/'
$powershellClientId = '0a7bdc5c-7b57-40be-9939-d4c5fc7cd417'
#region Auth
if ($Credential) {
$adminToken = Get-AzureStackToken `
-Authority $authority `
-Resource $activeDirectoryServiceEndpointResourceId `
-AadTenantId $AADDomain `
-ClientId $powershellClientId `
-Credential $Credential
}
else {
$adminToken = Get-AzureStackToken `
-Authority $authority `
-Resource $activeDirectoryServiceEndpointResourceId `
-AadTenantId $AADDomain `
-ClientId $powershellClientId
}
if (!$adminToken) {
Return
}
#endregion
#Setup REST call variables
$headers = @{ Authorization = (('Bearer {0}' -f $adminToken)) }
$armEndpoint = 'https://{0}.{1}' -f $api, $AzureStackDomain
if (!$Subscription) {
#Get default subscription ID
$uri = $armEndpoint + '/subscriptions?api-version=2015-01-01'
$result = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers
$Subscription = $result.value[0].subscriptionId
}
$usageResourceType = "Microsoft.Commerce/locations/subscriberUsageAggregates"
#build usage uri
if (!$TenantUsage) {
$uri = $armEndpoint + '/subscriptions/{0}/providers/Microsoft.Commerce/subscriberUsageAggregates?api-version=2015-06-01-preview&reportedstartTime={1:s}Z&reportedEndTime={2:s}Z&showDetails=true&aggregationGranularity={3}' -f $Subscription, $StartTime, $EndTime, $Granularity
if ($TenantUsage)
{
$usageResourceType = "Microsoft.Commerce/locations/UsageAggregates"
}
else {
$uri = $armEndpoint + '/subscriptions/{0}/providers/Microsoft.Commerce/UsageAggregates?api-version=2015-06-01-preview&reportedstartTime={1:s}Z&reportedEndTime={2:s}Z&showDetails=true&aggregationGranularity={3}' -f $Subscription, $StartTime, $EndTime, $Granularity
}
Do {
$result = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers -ErrorVariable RestError -Verbose
if ($RestError) {
return
}
$usageSummary = @()
$uri = $result.NextLink
$count = $result.value.Count
$Total += $count
$result.value | ForEach-Object {
$record = New-Object -TypeName System.Object
$resourceInfo = ($_.Properties.InstanceData |ConvertFrom-Json).'Microsoft.Resources'
$resourceText = $resourceInfo.resourceUri.Replace('\', '/')
$subscription = $resourceText.Split('/')[2]
$resourceType = $resourceText.Split('/')[7]
$resourceName = $resourceText.Split('/')[8]
#$record | Add-Member -Name Name -MemberType NoteProperty -Value $_.Name
#$record | Add-Member -Name Type -MemberType NoteProperty -Value $_.Type
$record | Add-Member -Name MeterId -MemberType NoteProperty -Value $_.Properties.MeterId
if ($meters.ContainsKey($_.Properties.MeterId)) {
$record | Add-Member -Name MeterName -MemberType NoteProperty -Value $meters[$_.Properties.MeterId]
}
$record | Add-Member -Name Quantity -MemberType NoteProperty -Value $_.Properties.Quantity
$record | Add-Member -Name UsageStartTime -MemberType NoteProperty -Value $_.Properties.UsageStartTime
$record | Add-Member -Name UsageEndTime -MemberType NoteProperty -Value $_.Properties.UsageEndTime
$record | Add-Member -Name additionalInfo -MemberType NoteProperty -Value $resourceInfo.additionalInfo
$record | Add-Member -Name location -MemberType NoteProperty -Value $resourceInfo.location
$record | Add-Member -Name tags -MemberType NoteProperty -Value $resourceInfo.tags
$record | Add-Member -Name subscription -MemberType NoteProperty -Value $subscription
$record | Add-Member -Name resourceType -MemberType NoteProperty -Value $resourceType
$record | Add-Member -Name resourceName -MemberType NoteProperty -Value $resourceName
$record | Add-Member -Name resourceUri -MemberType NoteProperty -Value $resourceText
$usageSummary += $record
}
$usageSummary | Export-Csv -Path $CsvFile -Append -NoTypeInformation
if ($PSBoundParameters.ContainsKey(Debug)) {
$result.value | Export-Csv -Path "$CsvFile.raw" -Append -NoTypeInformation
}
$params = @{
ResourceName = '../'
ResourceType = $usageResourceType
ApiVersion = "2015-06-01-preview"
ODataQuery = "reportedStartTime={0:s}&reportedEndTime={1:s}&showDetails=true&aggregationGranularity={2}" -f $StartTime, $EndTime, $Granularity
}
While ($count -ne 0)
$result = Get-AzureRmResource @params -ErrorVariable RestError -Verbose
if ($RestError)
{
return
}
$usageSummary = @()
$count = $result.Count
$Total += $count
$result | ForEach-Object
{
$record = New-Object -TypeName System.Object
$resourceInfo = ($_.Properties.InstanceData | ConvertFrom-Json).'Microsoft.Resources'
$resourceText = $resourceInfo.resourceUri.Replace('\', '/')
$subscription = $resourceText.Split('/')[2]
$resourceType = $resourceText.Split('/')[7]
$resourceName = $resourceText.Split('/')[8]
#$record | Add-Member -Name Name -MemberType NoteProperty -Value $_.Name
#$record | Add-Member -Name Type -MemberType NoteProperty -Value $_.Type
$record | Add-Member -Name MeterId -MemberType NoteProperty -Value $_.Properties.MeterId
if ($meters.ContainsKey($_.Properties.MeterId)) {
$record | Add-Member -Name MeterName -MemberType NoteProperty -Value $meters[$_.Properties.MeterId]
}
$record | Add-Member -Name Quantity -MemberType NoteProperty -Value $_.Properties.Quantity
$record | Add-Member -Name UsageStartTime -MemberType NoteProperty -Value $_.Properties.UsageStartTime
$record | Add-Member -Name UsageEndTime -MemberType NoteProperty -Value $_.Properties.UsageEndTime
$record | Add-Member -Name additionalInfo -MemberType NoteProperty -Value $resourceInfo.additionalInfo
$record | Add-Member -Name location -MemberType NoteProperty -Value $resourceInfo.location
$record | Add-Member -Name tags -MemberType NoteProperty -Value $resourceInfo.tags
$record | Add-Member -Name subscription -MemberType NoteProperty -Value $subscription
$record | Add-Member -Name resourceType -MemberType NoteProperty -Value $resourceType
$record | Add-Member -Name resourceName -MemberType NoteProperty -Value $resourceName
$record | Add-Member -Name resourceUri -MemberType NoteProperty -Value $resourceText
$usageSummary += $record
}
$usageSummary | Export-Csv -Path $CsvFile -Append -NoTypeInformation
if ($PSBoundParameters.ContainsKey('Debug'))
{
$result | Export-Csv -Path "$CsvFile.raw" -Append -NoTypeInformation
}
Write-Host "Complete - $Total Usage records written to $CsvFile"
}
#Main
$aadCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList '<user@domain>', (ConvertTo-SecureString -String 'XXX' -AsPlainText -Force)
Export-AzureStackUsage -StartTime 3/1/2017 -EndTime 3/13/2017 -AzureStackDomain 'local.azurestack.external' -AADDomain '<domain>' -Credential $aadCred -Granularity Hourly -Debug -Force
Export-AzsUsage -StartTime 6/10/2017 -EndTime 6/11/2017 -Granularity Hourly -Force