Upgrading Tier (Sku) via Set-AzureRmAnalysisServicesServer not working - powershell

I want to upscale and downscale my Azure Analysis Services with PowerShell (Automation Runbook), but changing the Tier (Sku) doesn't seem to work. However there are no errors. Any suggestions?
# PowerShell code
# Connect to a connection to get TenantId and SubscriptionId
$Connection = Get-AutomationConnection -Name "AzureRunAsConnection"
$TenantId = $Connection.TenantId
$SubscriptionId = $Connection.SubscriptionId
# Get the service principal credentials connected to the automation account.
$null = $SPCredential = Get-AutomationPSCredential -Name "SSISJoost"
# Login to Azure ($null is to prevent output, since Out-Null doesn't work in Azure)
Write-Output "Login to Azure using automation account 'SSISJoost'."
$null = Login-AzureRmAccount -TenantId $TenantId -SubscriptionId $SubscriptionId -Credential $SPCredential
# Select the correct subscription
Write-Output "Selecting subscription '$($SubscriptionId)'."
$null = Select-AzureRmSubscription -SubscriptionID $SubscriptionId
# Get variable values
$ResourceGroupName = Get-AutomationVariable -Name 'ResourceGroupName'
$AnalysisServerName = Get-AutomationVariable -Name 'AnalysisServerName'
# Get old status (for testing/logging purpose only)
$OldAsSetting = Get-AzureRmAnalysisServicesServer -ResourceGroupName $ResourceGroupName -Name $AnalysisServerName
try
{
# changing tier
Write-Output "Upgrade $($AnalysisServerName) to S1. Current tier: $($OldAsSetting.Sku.Name)"
Set-AzureRmAnalysisServicesServer -ResourceGroupName $ResourceGroupName -Name $AnalysisServerName -Sku "S1"
}
catch
{
Write-Error -Message $_.Exception
throw $_.Exception
}
Write-Output "Done"
# Get new status (for testing/logging purpose only)
$NewAsSetting = Get-AzureRmAnalysisServicesServer -ResourceGroupName $ResourceGroupName -Name $AnalysisServerName
Write-Output "New tier: $($NewAsSetting.Sku.Name)"
using Set-AzureRmAnalysisServicesServer

There was a little bug in the PowerShell AzureRM.AnalysisServices module. It has been fixed in 0.4.0 (Thursday, June 08 2017)
Now the code finally works: http://microsoft-bitools.blogspot.com/2017/06/schedule-upscaledownscale-azure.html

Related

Why would Test-AzureName always return false?

Running this script in Azure:
Write-Host "Running ps_example.ps1"
$resourceGroupName = 'myGroupName'
$storageName = "psexample"
$storageType = "Standard_LRS"
$location = "centralus"
if (Test-AzureName -Storage $storageName) {
Write-Host "Use existing storage account - $storageName"
} Else {
Write-Host "Make new storage account - $storageName"
New-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -Name $storageName -Type $storageType -Location $location
}
The first run shows:
Running ps_example.ps1
Make new storage account - psexample
The second run shows:
Running ps_example.ps1
Make new storage account - psexample
The storage account named psexample is already taken.
Why? That would seem to indicate that if (Test-AzureName -Storage $storageName) always returns false.
If I tell Azure to use powershell 1, the version is 1.113.5. Requesting version 2.0 results in 2.0.11. The behavior is the same for both.
EDIT:
Running this:
$result = Test-AzureName -Storage $storageName
Write-Host $result
always prints False, whether psexample exists or not.
You are combining RM and SM cmdlets in Azure. Test-AzureName is a Service Management cmdlet, while New-AzureRmStorageAccount is a Resource Manager cmdlet.
You may want to try to use
if ((Get-AzureRmStorageAccountNameAvailability -Name $storageName).NameAvailable) {
Write-Host "Make new storage account - $storageName"
New-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -Name $storageName -Type $storageType -Location $location
} Else {
Write-Host "Use existing storage account - $storageName"
}
to check for the name or you can create your storage account with:
New-AzureStorageAccount
Depending on what you want to use, SM or RM.

Failure when creating service fabric cluster with powershell

I'm trying to create a service fabric cluster with a powershell script. Here's the script:
Param(
[Parameter(HelpMessage="Azure user name")]
[String]$azUserName,
[Parameter(HelpMessage="Azure password")]
[String]$azPassword,
[Parameter(HelpMessage="What is the resource group name?")]
[String]$ResourceGroupName="sfLinuxClusterRg",
[Parameter(HelpMessage="What is the key vault group name?")]
[String]$KeyVaultResourceGroupName="KeyVaultRg",
[Parameter(HelpMessage="Where is the azure location?")]
[String]$Location="uksouth",
[Parameter(HelpMessage="what is the key vault group?")]
[String]$VaultGroupName="linuxclusterkeyvaultgroup",
[Parameter(HelpMessage="Where is the certificate stored locally?")]
[String]$CertFileName="certificate.pfx",
[Parameter(HelpMessage="What is the subscription id?")]
[String]$SubscriptionId,
[Parameter(HelpMessage="What is the tenant id?")]
[String]$TenantId
)
Function DecryptSecureString([SecureString] $secureText){
return [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureText))
}
Function CreateKeyVaultCert(){
try{
Select-AzureRmSubscription -SubscriptionId $SubscriptionId `
-TenantId $TenantId
# Create a Resource Group to hold your Key Vault(s)
# Note this should be separate from your other resources so you can delete those other resource groups without impacting your registered certs
New-AzureRmResourceGroup -Name $KeyVaultResourceGroupName -Location uksouth -Force
# Create a Key Vault to hold your secrets
New-AzureRmKeyVault -VaultName $vaultName -ResourceGroupName $KeyVaultResourceGroupName `
-Location uksouth -EnabledForDeployment `
-EnabledForDiskEncryption -EnabledForTemplateDeployment
# Have Key Vault create the certificate with a simple policy
$policy = New-AzureKeyVaultCertificatePolicy `
-SubjectName "CN=cluster123.uksouth.cloudapp.azure.com" `
-IssuerName Self -ValidityInMonths 12
Add-AzureKeyVaultCertificate -VaultName $vaultName -Name cert1 -CertificatePolicy $policy
Set-AzureRmKeyVaultAccessPolicy -VaultName $vaultName -EnabledForDeployment
Set-AzureRmKeyVaultAccessPolicy -VaultName $vaultName -EmailAddress $azUserName -PermissionsToSecrets Get
}
catch{
Write-Host $_.Exception.Message
exit
}
}
$azPassword = $azPassword | ConvertTo-SecureString -AsPlainText -Force
Import-AzureRmContext -Path "C:\stuff\AzureProfile.json"
$Date = Get-Date
$VaultName="VaultLearn" + $Date.ToString("hhmmss")
# sign in to your Azure account and select your subscription
$certName = "CN=cluster123.uksouth.cloudapp.azure.com"
$clustersize=5
$clustername = "cluster123" + $Date.ToString("hhmmss")
$adminuser="admin"
$vmsku = "Standard_D2_v2"
$os = "UbuntuServer1604"
Select-AzureRmSubscription -SubscriptionId $SubscriptionId
CreateKeyVaultCert
New-AzureRmServiceFabricCluster -Name $clustername `
-ResourceGroupName $ResourceGroupName `
-Location uksouth `
-ClusterSize $clustersize `
-VmUserName $adminuser -VmPassword $azPassword `
-CertificateSubjectName $certName `
-CertificatePassword $azPassword `
-VmSku $vmsku `
-CertificateOutputFolder 'C:\stuff' `
-OS $os `
-KeyVaultName $VaultName
Write-Host "Created service fabric cluster in resource group $ResourceGroupName"
#Add-AzureRmAccount
# $path = "C:\stuff\AzureProfile.json"
# Save-AzureRmContext -Path $path -Force
I keep getting the error:
New-AzureRmServiceFabricCluster : The name 'VaultLearn090903' is already in use.
This is really weird, because I'm pretty sure yesterday this script at least attempted to create the cluster, although I was getting another error about Ubuntu image not being found. What could be causing this error?
By the way, in order to run this script, I have previously run this code:
Add-AzureRmAccount
$path = "C:\stuff\AzureProfile.json"
Save-AzureRmContext -Path $path -Force
which has cached my azure credentials locally.
I have specifically added two statements into the script to add a policy for access to the keyvault:
Set-AzureRmKeyVaultAccessPolicy -VaultName $vaultName -EnabledForDeployment
Set-AzureRmKeyVaultAccessPolicy -VaultName $vaultName -EmailAddress $azUserName -PermissionsToSecrets Get
I know this is probably overkill, but I'm trying to get rid of this problem.
The other weird thing is I have tried the Azure Sample Github repo
I'm at a loss for how I can continue with service fabric.
For completeness:
I managed to get something different working by going to the azure portal, creating a service fabric cluster and downloading the ARM template (which includes some powershell scripts).
thanks

Azure Search set ReplicaCount by Automation graphical runbook

Azure Search does not give any scheduled scaling option so I try to make it by Automation account.
I followed AzSearch PowerShell command, but it does not work as I expected.
Set-AzureRmResource with ReplicaCount=2 parameter is not applied. Actually, it does not give any result message. What did I miss?
To reproduce my problem, you can import my runbook file at below link;
https://gist.github.com/YoungjaeKim/5cb66a666a3a864b7379aac0a400da40
Save the text file as AzureSearch-SetReplicaCount.graphrunbook and Import it to Automation account > Add a runbook menu.
Following commenters, I ended up by making PowerShell runbook.
I uploaded powershell source code to below link;
https://gallery.technet.microsoft.com/scriptcenter/Azure-Search-change-c0b49c4c
Let me attach the code as below;
<#
.DESCRIPTION
Scale Azure Search ReplicaCount
AzSearch command reference; https://learn.microsoft.com/en-us/azure/search/search-manage-powershell
.NOTES
AUTHOR: Youngjae Kim
LASTEDIT: June 19, 2017
#>
Param(
[string]$SubscriptionId,
[string]$ResourceGroupName,
[string]$AzSearchResourceName,
[int]$InstanceCount = 1
)
# 1. Acquire Automation account
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found. You must have Automation account. Reference: https://learn.microsoft.com/en-us/azure/automation/automation-role-based-access-control"
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
# 2. Select subscription
Select-AzureRmSubscription -SubscriptionId $SubscriptionId
# 3. Specify Azure Search Resource
$resource = Get-AzureRmResource `
-ResourceType "Microsoft.Search/searchServices" `
-ResourceGroupName $ResourceGroupName `
-ResourceName $AzSearchResourceName `
-ApiVersion 2015-08-19
Write-Output ($resource)
# 4. Scale your service up
# Note that this will only work if you made a non "free" service
# This command will not return until the operation is finished
Write-Output ("Updating InstanceCount to " + $InstanceCount + ". This can take 15 minutes or more...")
$resource.Properties.ReplicaCount = $InstanceCount
$resource | Set-AzureRmResource -Force -Confirm:$false
# 5. Finish
Write-Output ("End of Process to set InstanceCount = " + $InstanceCount + " for " + $AzSearchResourceName)

Monitoring Services on an Azure VM using an Azure Runbook

I have a Powershell script that enumerates running services and their current state using Get-WmiObject Win32_Service. Initial version based on this one and then modified for Azure. When I run the script in Powershell (without the azure automation parts) on my location machine it works fine and I can connect to all the machines of interest, but when I port it to a runbook i get the following error: "Get-WmiObject : The RPC server is unavailable."
Q: Is the problem with permissions for the automation account? If so, what account should I add to the local machines to resolve the issue?
Q: Is Get-WmiObject not a valid way to initiate the connection? If not, what should I try instead?
The code I'm using is below:
[CmdletBinding(SupportsShouldProcess = $true)]
param(
# Servers to check
[Parameter(Mandatory=$true)][string[]]$ServerList,
# Services to check for
[Parameter(Mandatory=$true)][string[]]$includeService
)
# Following modifies the Write-Verbose behavior to turn the messages on globally for this session
$VerbosePreference = "Continue"
$connectionName = "AzureRunAsConnection"
# retry
$retry = 6
$syncOk = $false
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
do
{
try
{
Add-AzureRmAccount -ServicePrincipal -TenantId $servicePrincipalConnection.TenantId -ApplicationId $servicePrincipalConnection.ApplicationId -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
$syncOk = $true
}
catch
{
$ErrorMessage = $_.Exception.Message
$StackTrace = $_.Exception.StackTrace
Write-Warning "Error during sync: $ErrorMessage, stack: $StackTrace. Retry attempts left: $retry"
$retry = $retry - 1
Start-Sleep -s 60
}
} while (-not $syncOk -and $retry -ge 0)
Select-AzureRMSubscription -SubscriptionId $SubscriptionId -TenantId $servicePrincipalConnection.TenantId
$currentSubscription = Get-AzureRMSubscription -SubscriptionId $SubscriptionId -TenantId $servicePrincipalConnection.TenantId
Set-AzureRmContext -SubscriptionId $SubscriptionId;
$props=#()
[System.Collections.ArrayList]$unreachableServers = #()
Foreach($ServerName in ($ServerList))
{
try
{
$service = Get-WmiObject Win32_Service -ComputerName $servername
}
catch
{}
if ($Service -ne $NULL)
{
foreach ($item in $service)
{
#$item.DisplayName
Foreach($include in $includeService)
{
#write-host $include
if(($item.name).Contains($include) -eq $TRUE)
{
$props += [pscustomobject]#{
servername = $ServerName
name = $item.name
Status = $item.Status
startmode = $item.startmode
state = $item.state
serviceaccount=$item.startname
DisplayName =$item.displayname}
}
}
}
}
else
{
Write-host "Failed to contact server: "$ServerName
$unreachableServers.Add($ServerName)
}
}
$props | Format-Table Servername,Name,startmode,state,serviceaccount,displayname -AutoSize
I am assuming that you are using the Azure Automation Hybrid Worker functionality. Be default it runs under the System account. However you can use a different account to run the runbook under. This is documented here: Azure Automation Hybrid Worker; Look under the RunAs account section. Use the same account that works when you try it directly.
have you considered using OMS? this sounds like a better thing to do.
Anyway, to answer your questions, I would probably create a local user and create a PS configuration endpoint for that user to connect to, and connect impersonating that user from the Automation Account, but again, I wouldn't even go this route, I'd rather use OMS.

Azure: How to check storage account exists in Azure with Get-AzureStorageAccount

I am building a power shell script to automate the setup of a website environment in Azure. This web uses an account storage. I want to the script not to create the account storage if exists.
I thought that using Get-AzureStorageAccount this way may work but it does not:
Write-Verbose "[Start] creating $Name storage account $Location location"
$storageAcct = Get-AzureStorageAccount –StorageAccountName $Name
if (!$storageAcct)
{
$storageAcct = New-AzureStorageAccount -StorageAccountName $Name -Location $Location -Verbose
if ($storageAcct)
{
Write-Verbose "[Finish] creating $Name storage account in $Location location"
}
else
{
throw "Failed to create a Windows Azure storage account. Failure in New-AzureStorage.ps1"
}
}
else
{
Write-Verbose "$Name storage account in $Location location already exists, skipping creation"
}
The issue is I don't know how to handle the return of Get-AzureStorageAccount.
Thank you very much in advance!
I would suggest using the Test-AzureName cmdlet to determine if it exists. So, something like this.
if (!(Test-AzureName -Storage $Name))
{
Write-Host "Creating Storage Account $Name"
New-AzureStorageAccount -StorageAccountName $Name -Location $Location
}
You can use Test-AzureName for other services too, such as Cloud Services, WebSites, and ServiceBus. It returns True if it exists, False otherwise.
Get-AzureRmStorageAccountNameAvailability -Name "accountname"
Try this:
$Name = "myStorageAccount"
$Location = "myLocation"
Write-Host "[Start] creating $Name storage account $Location location"
try{
Get-AzureStorageAccount –StorageAccountName $Name -ErrorAction Stop | Out-Null
Write-Host "$Name storage account in $Location location already exists, skipping creation"
}
catch{
Write-Host "[Finish] creating $Name storage account in $Location location"
New-AzureStorageAccount -StorageAccountName $Name -Location $Location -Verbose
}
Test-AzureName didn't work with our build agents and we already had a try/catch in code so a second one would require building it out as a function. I opted for that standard get and check if null, use -ErrorAction Ignore to stop it throwing an exception
# Check for storage account and create if not found
$StorageAccount = Get-AzureRmStorageAccount -Name $StorageAccountName -ResourceGroupName $StorageAccountRG -ErrorAction Ignore
if ($StorageAccount -eq $null)
{
New-AzureRmStorageAccount -Location "West Europe" -Name $StorageAccountName -ResourceGroupName $StorageAccountRG -SkuName Standard_LRS -Kind Storage
$StorageAccount = Get-AzureRmStorageAccount -Name $StorageAccountName -ResourceGroupName $StorageAccountRG
}
#Rick Rainey's solution works if you're logged in using Add-AzureAccount. However, Azure and powershell have a conflicting and confusing suite of login accounts (Windows Live versus AD) and login mechanisms (Classic: Add-AzureAccount; Resource manager: Login-AzureRmAccount). Some Azure powershell cmdlets require a specific login; further, some require a specific account type!
To clear through this thicket of complicated, undocumented, and confusing permission issues, we always use an AD account, logging in via Login-AzureRmAccount. We also use Azure resource manager (ARM) resources and cmdlets, following Microsoft's movement to ARM as its recommended and strategic approach. However, #RIck's solution is one which the ARM login doesn't work with. :-( So you need another approach, which is #Darren's (for storage). However, for a generic replacement for Test-AzureName I'd suggest Find-AzureRmResource. In the case of storage
$StorageObject = Find-AzureRmResource -ResourceType "Microsoft.Storage/storageAccounts" | Where-Object {$_.Name -eq $storageName}
if ( !$StorageObject ) {
$storageLocation = (Get-AzureRmResourceGroup -ResourceGroupName $resourceGroup).Location
$storageType = "Standard_LRS"
New-AzureRmStorageAccount -ResourceGroupName $resourceGroup -Name $storageName -Location $storageLocation -Type $storageType
}
You should use the latest Powershell module Az.
if ($(Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccountName) -eq $null)
{
# does not exist
}
With the current Az module for PowerShell Version 7, the Get-AzStorageAccountNameAvailability cmdlet might offer a more efficient solution as it was designed specifically for this task. Here is an example:
# ... declare variables and specify values ...
$checkNameAvail = (Get-AzStorageAccountNameAvailability -Name $storageAccountName) | `
Select-Object NameAvailable
if ($checkNameAvail.NameAvailable)
{
Write-Host 'Account name available! Please wait while your resource is being created'
# Create account. Variables used in this example would have been declared earlier in the script.
$storageAccount = (New-AzStorageAccount -ResourceGroupName $resourceGroupName `
-AccountName $storageAccountName `
-Location $location `
-SkuName $skuType `
-AllowBlobPublicAccess $false -EnableHttpsTrafficOnly $true)
# ...
}
else
{
# This section of the script executes if the name is not available
Write-Host "The name <$storageAccountName> is not available. Suggest a new globally unique name!"
}
The condition above will return False, and execute the else statement because the boolean value returned by the cmdlet is in [0] as shown in the PowerShell command-line test below. The availability information (boolean) can thus be stripped from the object returned by the cmdlet and (as in this example) used as a condition in the rest of the script.
PS C:\> Get-AzStorageAccountNameAvailability -Name testaccount1
NameAvailable Reason Message
------------- ------ -------
False AlreadyExists The storage account named testaccount1 is already taken.
Use the error variable
Get-AzStorageAccount -ResourceGroupName 'RG-QA-TEST' -Name 'staccountfor12334ff' -ErrorVariable ev1 -ErrorAction SilentlyContinue
if ($ev1) {
Write-Host "-------------------------- Creating OEM Storage"
//create storage account
}
I had this challenge when setting up Azure storage accounts for Static website hosting using Powershell in Octopus Deploy.
Here's how I fixed it:
Using the Az module for Azure Powershell I did the following:
# Define Variables
$RESOURCE_GROUP_NAME = my-resource-group
$LOCATION = northeurope
$STORAGE_ACCOUNT_NAME = myapplication
$SKU_NAME = Standard_GRS
$STORAGE_KIND = StorageV2
# Check Storage Account and Create if not Found
$STORAGE_ACCOUNT = Get-AzStorageAccount -ResourceGroupName $RESOURCE_GROUP_NAME -Name $STORAGE_ACCOUNT_NAME -ErrorAction Ignore
if ($STORAGE_ACCOUNT -eq $null) {
Write-Host 'Creating storage account'
New-AzStorageAccount -ResourceGroupName $RESOURCE_GROUP_NAME -AccountName $STORAGE_ACCOUNT_NAME -Location $LOCATION -SkuName $SKU_NAME -Kind $STORAGE_KIND
Write-Host "$STORAGE_ACCOUNT_NAME storage account successfully created"
}
else {
Write-Host "$STORAGE_ACCOUNT_NAME storage account already exists"
}
Note:
-ErrorAction Ignore - This ignores the exception that would arise if the storage account does not exist
Write-Host " " - Double quotes were used to allow for string interpolation since we are connecting strings and variables.
That's all.
I hope this helps