I am using Automation Account with execution of PowerShell Runbook for Pausing my Azure Datawarehouse database.
Setup is completed with creation of crendentials, certificate for Thumbprints.
When I executed the PS script and completed with error message
No Azure SQL Data Warehouse named ADWPOC exist on SQL Server At SuspendOrPauseAzureSQLDataWarehouse:72 char:72 + + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
I have provided the name of database and server details correctly while executing this script. I am not sure what is the problem here. Please advise.
I have imported the PS script from runbook gallery "Suspend Or Pause Azure SQL Data Warehouse". Please let me know if you want me to attach the script here?
Not sure, but the script looks too old, it still uses the AzureRm module which has been deprecated.
To pause the data warehouse in the runbook, I recommend you to use new Az module, sample here, to use that in runbook, just follow the steps as below.
1.Navigate to your automation account in the portal -> Modules, make sure you have imported the Az.Accounts and Az.Sql modules, if not, in the Modules -> Browse Gallery, search for the modules and import them.
2.After importing the modules successfully, navigate to the Runbooks -> create a PowerShell runbook(not the PowerShell Workflow), then use the script as below in the runbook.
Note: The <server-name> should be like testserver, not testserver.database.windows.net.
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
Connect-AzAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
$database = Get-AzSqlDatabase –ResourceGroupName "<resource-group-name>" –ServerName "<server-name>" –DatabaseName "<data-warehouse-name>"
if($database){
if($database.Status -eq 'Paused'){
Write-Output "The Data Warehouse was already paused."
}else{
$database | Suspend-AzSqlDatabase
Write-Output "The Data Warehouse has been paused."
}
}else{
Write-Output "The Data Warehouse does not exist."
}
Related
Azure Automation runbook fails when triggered from a Webhook
We have a runbook that runs just fine when launched via the “Start” button in the Azure Portal.
The exact same runbook fails when launched from a webhook using the exact same parameters.
The issue is that after the code in the runbook opens a valid connection to Azure, it tries to get one of the databases we are going to work with and it fails with an exception that reads “Resource group '''' could not be found.”
The same exact code and parameters work without any issues when run outside the Webhook.
We added code to get the context after the code does the login and we checked that the context name, subscription ID and Tenant ID are valid, and we even pass the context to the Get-AzSqlDatabase call and still it fails when triggered via the webhook. We are not sure what else we can try to diagnose and correct the issue.
Here is a sample of the code we run and where it fails...
. . .
Function Login {
Disable-AzContextAutosave -Scope Process
Write-Output "Logging in to Azure..."
$connectionName = "GoodTestingConnection"
try{
Connect-AzAccount -ServicePrincipal -Tenant $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
Write-Output "Error loging in to Azure: $_"
throw "Error loging in to Azure: $_"
}
}
$ErrorActionPreference = "Stop"
if ($WebHookData) {
Write-Output "Running runbook from web hook request"
$wbRunParams = (ConvertFrom-Json -InputObject $WebHookData.RequestBody)
Write-Output "Webhook parameters $wbRunParams"
$client = $wbRunParams.client
Write-Output "Running process for client $client"
}
Login
$ctx = Get-AzContext
Write-Output "Context nanme: $($ctx.Name)"
Write-Output "Environment name: $($ctx.Environment.Name)"
Write-Output "Subscription ID: $($ctx.Subscription.Id)"
Write-Output "Tenant ID: $($ctx.Tenant.Id)"
Write-Output "Getting the 'from' Db..."
$fromDb = Get-AzSqlDatabase `
-DatabaseName $copyFromDbName `
-ServerName $copyFromServer `
-ResourceGroupName $copyFromRG `
-DefaultProfile $ctx
$fromDb
#The code never reaches this point as it fails on the previous call
. . .
I had the same issue. Here is what worked for me.
When the automation runbook is triggered via the start option or via the test pane, the, the format needs to be converted. This is when you would use
$wbRunParams = (ConvertFrom-Json -InputObject $WebHookData.RequestBody)
When the runbook has to be triggered directly by webhook, no need to convert and the below would work.
$wbRunParams = $WebHookData.RequestBody
The following code works great via Azure Cloud Shell (completes, App Service deleted as expected).
Remove-AzWebApp -ResourceGroupName "ResourceGroup1" -Name "AppService1" -Force
It also completes without error within my Runbook workflow, but the App Service remains operational. This feels like a permissions problem, but I've tried adding the Owner role at the subscription level without success.
Any ideas/tips for how to make this work for the AzureRunAsConnection account?
This feels like a permissions problem, but I've tried adding the Owner role at the subscription level without success.
It is not a permission problem, when you create the automation account along with the RunAsAccount, it will add the service principal related to the RunAsAccount to the subscription as a Contributor role, which is enough to remove the web app.
If you are using the PowerShell Workflow Runbook, try the sample below, it works for me. (First, make sure you have installed the Az.Accounts, Az.Websites modules in the automation account -> Modules.)
workflow testrun3
{
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
Connect-AzAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
Remove-AzWebApp -ResourceGroupName "<group-name>" -Name "joywebapp1234" -Force
}
Check the result in the portal:
To create or update a Run As account, you must have specific privileges and permissions. An Application administrator in Azure Active Directory and an Owner in a subscription can complete all the tasks. Use Remove-AzAutomationConnection to remove an Automation connection.
For more details, you could refer to this article about Run As account permissions.
Simply, I'm running Connect-AzureRmAccount using runbook automation in Azure, it gives me the error below:
Unable to find an entry point named 'GetPerAdapterInfo' in DLL
'iphlpapi.dll'.
I already imported the Azureprofile module and I can not figure out what is the issue.
If you want to connect to the Azure account with the PowerShell command Connect-AzureRmAccount in your Runbook, then it is really unnecessary. Just as I said in the comment, when you use the Runbook, you are already in an exact subscription of the tenant with an account. So just run your script without connecting the account.
If you really want to connect with the PowerShell, you can use the service principal like this:
Disable-AzureRmContextAutosave –Scope Process
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Connect-AzureRmAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationID $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint
But I really suggest you can just run the PowerShell script in your Runbook directly.
Update
When you create the Runbook, there will be a connection for you to run the PowerShell script. Or you can create the connection as your requirement. See Connection assets in Azure Automation. You could just use the default connection use the code like this:
$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."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
I had the same problem, in my case I was trying to simply use the Azure Cmdlet Get-AzVm.
I previously used code similar to what Charles posted above, the problem is that doesn't work with the Az Cmdlets as you can't use both the AzureRM and the new Azure modules at the same time.
I replaced all of that with the following and now it works:
Disable-AzContextAutosave –Scope Process
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Connect-AzAccount -ServicePrincipal -Tenant $Conn.TenantID `
-ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint
$AzureContext = Select-AzSubscription -SubscriptionId $Conn.SubscriptionID
I found this in the following article: https://learn.microsoft.com/en-us/azure/automation/automation-first-runbook-textual
I would like to know how to create an alert for an Azure VM which tells me if the server(s) is running at a specific time.
The scenario:
Servers for the Azure network need to start at 7:30am to be ready for the users as they shut down at 7:30pm each day to save $$.
Today the azure automation script could not find any vms for the resource group! So that meant the servers where not started. I want to create an alert that will only tell me if the server(s) are not running at say 7:45am. So I can start them.
(Running the script now does find all of the servers now but didn't before for some reason... maybe Azure was moving the vms in the resource group?)
I have looked at:
- Microsoft Operations Management Suit > Log Search > Add Alert Rule.
- Resource Manager > Virtual Machines > Monitoring > Alert Rules > Add metic alert & Add activity log alert.
But I can't see where to only run the alert at a specific time.
Update/Edit:
Script used:
param (
[Parameter(Mandatory=$false)]
[String]$AzureCredentialAssetName = 'AzureCred',
[Parameter(Mandatory=$false)]
[String]$AzureSubscriptionIDAssetName = 'AzureSubscriptionId'
)
# Setting error and warning action preferences
$ErrorActionPreference = "SilentlyContinue"
$WarningPreference = "SilentlyContinue"
# Connecting to Azure
$Cred = Get-AutomationPSCredential -Name $AzureCredentialAssetName -ErrorAction Stop
$null = Add-AzureAccount -Credential $Cred -ErrorAction Stop -ErrorVariable err
$null = Add-AzureRmAccount -Credential $Cred -ErrorAction Stop -ErrorVariable err
# Selecting the subscription to work against
$SubID = Get-AutomationVariable -Name $AzureSubscriptionIDAssetName
Select-AzureRmSubscription -SubscriptionId $SubID
# Getting all resource groups
$ResourceGroup = "Servers"
# Getting all virtual machines
$RmVMs = (Get-AzureRmVM -ResourceGroupName $ResourceGroup -ErrorAction $ErrorActionPreference -WarningAction $WarningPreference).Name
# Managing virtual machines deployed with the Resource Manager deployment model
"Loop through all VMs in resource group $ResourceGroup."
if ($RmVMs)
{
foreach ($RmVM in $RmVMs)
{
"`t$RmVM found ..."
$RmPState = (Get-AzureRmVM -ResourceGroupName $ResourceGroup -Name $RmVM -Status -ErrorAction $ErrorActionPreference -WarningAction $WarningPreference).Statuses.Code[1]
if ($RmPState -eq 'PowerState/deallocated')
{
"`t$RmVM is starting up ..."
$RmSState = (Start-AzureRmVM -ResourceGroupName $ResourceGroup -Name $RmVM -ErrorAction $ErrorActionPreference -WarningAction $WarningPreference).IsSuccessStatusCode
if ($RmSState -eq 'True')
{
"`t$RmVM has been started."
}
else
{
"`t$RmVM failed to start."
}
}
}
}
else
{
"No VMs for $ResourceGroup deployed with the Resource Manager deployment model."
}
"Runbook Completed."
I just want a fail safe to know if the servers are not running when they should be.
Expected output:
Loop through all VMs in resource group Servers.
DOMAINCONTROLLER found ...
SQLSERVER found ...
GATEWAY found ...
APPLICATIONHOST found ...
Runbook Completed.
instead of:
Loop through all VMs in resource group Servers.
No VMs for Servers deployed with the Resource Manager deployment model.
Runbook Completed.
I.e. rerunning the same script manually gave expected results.
Based on my knowledge, Azure metric alert could not send mail when your VM has been started or stopped at a specific time.
According to your description, Start/Stop VMs during off-hours [Preview] solution in Automation is a good solution for you to save money.
The Start/Stop VMs during off-hours [Preview] solution starts and stops your Azure Resource Manager virtual machines on a user-defined schedule and provides insight into the success of the Automation jobs that start and stop your virtual machines with OMS Log Analytics.
It could send email notifications when the start and stop VM runbooks complete.
You also could use Azure automation to start or stop VM for a specific time, more information please refer to this link.
Update:
Your script works for me. I check your script, $RmVMs = (Get-AzureRmVM -ResourceGroupName $ResourceGroup -ErrorAction $ErrorActionPreference -WarningAction $WarningPreference).Name returns null. Do you have multiple subscriptions? It seems that your subscription ID is wrong. Please ensure your subscription ID is right. You could get your subscription ID on your local PowerShell.
Get-AzureRmSubscription
Update2:
You could save your save your subscription to automation connection. You could use the script below:
param (
[Parameter(Mandatory=$false)]
[String]$AzureCredentialAssetName
)
# Authenticate to Azure with certificate
Write-Verbose "Get connection asset: $ConnectionAssetName" -Verbose
$connectionName = Get-AutomationConnection -Name $AzureCredentialAssetName
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $AzureCredentialAssetName
"Logging in to Azure..."
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
$ResourceGroup = "shui2"
.....
I'd like to use a powershell script in Azure automation to schedule switching on/off resources.
I'd like to do this without creating an account as our domain enforces password resets. I know that the automation account creates a certificate - is it possible to authenticate with this instead, when using the resource manager (AKA not a "classic" account).
Yes, this is a valid approach, in fact if you create an Azure Automation account and use the defaults it will create that for you and you can use that transparently. Taken from example runbook:
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
$null = Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
dozen edits because my brain stopped working