Can I automatically start and stop an azure website on a schedule? - azure

Even asking this question, I'm wondering how something so simple can be so difficult for me. All I want to do is automate the stopping and starting of an Azure WebSite on a schedule. At first, I looked at WebJobs, and created a powershell script that would stop the WebSite that used the stop-azurewebsite commandlet:
stop-azurewebsite [my site]
I then created a .cmd file to call it using powershell.exe to execute the powershell file
PowerShell.exe -ExecutionPolicy RemoteSigned -File stopit.ps1
I created a WebJob to run the powershell command to stop the site, but it errored with a message saying:
stop-azurewebsite : The term 'stop-azurewebsite' is not recognized as the name
of a cmdlet, function, script file, or operable program. Check the spelling of
the name, or if a path was included, verify that the path is correct and try
again.
So, I figured I'd go the REST API route. I created a post request using fiddler and the proper management certificate to make a call to:
https://management.core.windows.net/[my subscription id]/services/WebSpaces/[webspace]/sites/[website name]/stop
Turns out, there is no 'stop' command. There's 'restart', but that's obviously of no use in this situation. So, all that said, what is a reasonable way to automate the stopping and subsequent (but much later) starting of an Azure WebSite on a specific time schedule?
UPDATE:
I've figured out how to issue the http request to stop the site using a PUT to
https://management.core.windows.net/[my subscription id]/services/WebSpaces/[webspace]/sites/[website name] with a body of {"State":"Stopped"}, but I still don't have an obvious way of 'PUT`ing' to this URL in a WebJob.

Use Azure Automation, create a runbook and add the code below to get all 'Running' websites/webapps and shut them down.
# Get Websites/webapps
$websites = Get-AzureWebsite | where-object -FilterScript{$_.state -eq 'Running' }
# Stop each website
foreach -parallel ($website In $websites)
{
$result = Stop-AzureWebsite $website.Name
if($result)
{
Write-Output "- $($website.Name) did not shutdown successfully"
}
else
{
Write-Output "+ $($website.Name) shutdown successfully"
}
}
Publish the runbook and you should be able to schedule it straight in Azure Portal. Make sure your automated user is authenticated and your subscription selected in the runback and there should be no problems.
Similarly for starting up all websites/webapps just change 'Running' to 'Stopped' and 'Stop-AzureWebsite' to 'Start-AzureWebsite'.

Take a look at Azure Automation. It lets you run Powershell scripts on a schedule and is a much easier way to run automation scripts that will start/stop/modify your sites.

It's even easier now to do things on schedules using Azure Scheduler, especially in this situation. Stopping a website by simply making that API call with a scheduled job. Take a look at https://azure.microsoft.com/en-us/services/scheduler/

Related

Running Azure Powershell Inline Script

I have a powershell script in order to make a backup of a SQL Database. I run the script locally, i run the script on TFS release phase with Powershell Script (not the azure powershell task), and everything went well.
Now, i want it to run it with the Azure PowerShell script: InlineScript because i want to remove the login part from my powershell. I saved the username \ password in the variables in order to login and i want to get rid of that
This is the script :
Please notice that i put the Login-AzureRmAccount because of the error. After this, i'm still getting it.
Error message:
[error]Showing a modal dialog box or form when the application is not running in UserInteractive mode is not a valid operation. Specify the ServiceNotification or DefaultDesktopOnly style to display a notification from a service application.
[error]Run Login-AzureRmAccount to login.
As mentioned above please change the dropdown to "Azure Resource Manager" because in Azure classic this command will translate to Start-AzureSqlDatabaseCopy which does not have all the options available
https://learn.microsoft.com/en-us/powershell/module/servicemanagement/azure/start-azuresqldatabasecopy?view=azuresmps-4.0.0

How to run a remote command (powershell/bash) against an existing Azure VM in Azure Data Factory V2?

I've been trying to find a way to run a simple command against one of my existing Azure VMs using Azure Data Factory V2.
Options so far:
Custom Activity/Azure Batch won't let me add existing VMs to the pool
Azure Functions - I have not played with this but I have not found any documentation on this using AZ Functions.
Azure Cloud Shell - I've tried this using the browser UI and it works, however I cannot find a way of doing this via ADF V2
The use case is the following:
There are a few tasks that are running locally (Azure VM) in task scheduler that I'd like to orchestrate using ADF as everything else is in ADF, these tasks are usually python applications that restore a SQL Backup and or purge some folders.
i.e. sqdb-restore -r myDatabase
where sqldb-restore is a command that is recognized locally after installing my local python library. Unfortunately the python app needs to live locally in the VM.
Any suggestions? Thanks.
Thanks to #martin-esteban-zurita, his answer helped me to get to what I needed and this was a beautiful and fun experiment.
It is important to understand that Azure Automation is used for many things regarding resource orchestration in Azure (VMs, Services, DevOps), this automation can be done with Powershell and/or Python.
In this particular case I did not need to modify/maintain/orchestrate any Azure resource, I needed to actually run a Bash/Powershell command remotely into one of my existing VMs where I have multiple Powershell/Bash commands running recurrently in "Task Scheduler".
"Task Scheduler" was adding unnecessary overhead to my data pipelines because it was unable to talk to ADF.
In addition, Azure Automation natively only runs Powershell/Python commands in Azure Cloud Shell which is very useful to orchestrate resources like turning on/off Azure VMs, adding/removing permissions from other Azure services, running maintenance or purge processes, etc, but I was still unable to run commands locally in an existing VM. This is where the Hybrid Runbook Worker came into to picture. A Hybrid worker group
These are the steps to accomplish this use case.
1. Create an Azure Automation Account
2. Install the Windows Hybrid Worker in my existing VM . In my case it was tricky because my proxy was giving me some errors. I ended up downloading the Nuget Package and manually installing it.
.\New-OnPremiseHybridWorker.ps1 -AutomationAccountName <NameofAutomationAccount> -AAResourceGroupName <NameofResourceGroup>
-OMSResourceGroupName <NameofOResourceGroup> -HybridGroupName <NameofHRWGroup>
-SubscriptionId <AzureSubscriptionId> -WorkspaceName <NameOfLogAnalyticsWorkspace>
Keep in mind that in the above code, you will need to find your own parameter values, the only parameter that does not have to be found and will be created is HybridGroupName this will define the name of the Hybrid Group
3. Create a PowerShell Runbook
[CmdletBinding()]
Param
([object]$WebhookData) #this parameter name needs to be called WebHookData otherwise the webhook does not work as expected.
$VerbosePreference = 'continue'
#region Verify if Runbook is started from Webhook.
# If runbook was called from Webhook, WebhookData will not be null.
if ($WebHookData){
# Collect properties of WebhookData
$WebhookName = $WebHookData.WebhookName
# $WebhookHeaders = $WebHookData.RequestHeader
$WebhookBody = $WebHookData.RequestBody
# Collect individual headers. Input converted from JSON.
$Input = (ConvertFrom-Json -InputObject $WebhookBody)
# Write-Verbose "WebhookBody: $Input"
#Write-Output -InputObject ('Runbook started from webhook {0} by {1}.' -f $WebhookName, $From)
}
else
{
Write-Error -Message 'Runbook was not started from Webhook' -ErrorAction stop
}
#endregion
# This is where I run the commands that were in task scheduler
$callBackUri = $Input.callBackUri
# This is extremely important for ADF
Invoke-WebRequest -Uri $callBackUri -Method POST
4. Create a Runbook Webhook pointing to the Hybrid Worker's VM
4. Create a webhook activity in ADF where the above PowerShell runbook script will be called via a POST Method
Important Note: When I created the webhook activity it was timing out after 10 minutes (default), so I noticed in the Azure Automation Account that I was actually getting INPUT data (WEBHOOKDATA) that contained a JSON structure with the following elements:
WebhookName
RequestBody (This one contains whatever you add in the Body plus a default element called callBackUri)
All I had to do was to invoke the callBackUri from Azure Automation. And this is why in the PowerShell runbook code I added Invoke-WebRequest -Uri $callBackUri -Method POST. With this, ADF was succeeding/failing instead of timing out.
There are many other details that I struggled with when installing the hybrid worker in my VM but those are more specific to your environment/company.
This looks like a use case that is supported with Azure Automation, using a hybrid worker. Try reading here: https://learn.microsoft.com/en-us/azure/automation/automation-hybrid-runbook-worker
You can call runbooks with webhooks in ADFv2, using the web activity.
Hope this helped!

Azure powershell runbook don't show any output

I have a simple Azure PowerShell runbook script
workflow CheckIdentityColumns
{
Write-Output "Test Output"
}
When I am trying to test it I don't see any output.
Why?
This is because your flow is Powershell runbook not Powershell Workflow runbook .
In Powershell runbook, you don't need to use
workflow CheckIdentityColumns{}
declaration. This is the main reason why it doesn't work.
I tried your scenario and it worked for me. You can view the details below.
This happened to me in different scenario. The answer I got from Microsoft support was that the Runbook in the cache is still the older one, i.e. an empty Runbook in your case. All you need to do is:
Publish the Runbook and edit and test again
If it still doesn't work then clear the cache and restart your browser
Test Runbook:
Output:

Does Azure Automation support Write-Information?

I want to write info logs into Azure Automation job logs. I've created the simple PowerShell runbook
$InformationPreference = "Continue"
Write-Information "Hello info"
Write-Verbose "Hello Verbose"
Write-Warning "Hello warning"
Write-Error "Hello error"
And in runbook execution All logs I see only verbose, warning and error logs
If to disable runbook Verbose logs I see only warnings and errors. Locally it works fine but not in Azure. I've also tried Write-Information "Hello info" -InformationAction Continue - didn't help.
Write-Information appeared in PowerShell 5.0. I've checked the PS version in Azure Automation sandbox machine by using $PSVersionTable - it's more than 5. So, should work.
Do you know if they support it or not?
If you want to write info logs into Azure Automation job logs, I suggest you use write-output.
For details, you can refer to this article.
I'm not sure if write-information is supported or not in runbook. I test it at my side, as well as I test the cmdlet write-host which is a wrapper for write-information. But no message output for both of them.
A support ticket is raised for confirmation from MS.
Hope this helps.
Azure Automation does not fully support the Information stream at this point. PowerShell 5 support is not enough: your runbook will not fail, but Automation will not capture and store the Information stream content, and this is why you will not see it in the logs.
I do wish Write-Information was available in Azure Automation.
Using Write-Output in a function that you want to return something else (like a Boolean) is quite problematic.

What is a method for checking where an Azure Automation runbook (PowerShell) is running?

I'm writing a set of PowerShell runbooks in Azure Automation. Some of them run on-premises (ala Hybrid Runbook Worker) and some in Azure directly.
I'd like to immediately error and exit any hybrid scripts if they are accidentally kicked off in Azure (since it's the default selection when using the portal).
I thought I check by getting the results of Get-AutomationConnection -Name AzureRunAsConnection but it takes about 4 seconds to respond, but it also returns values when run via Hybrid Worker. Does anyone know of a better/quicker method?
Thanks!
Update: A one-liner that is crude but seems to work is:
Try {$AmIInAzure = Get-AzureRmEnvironment AzureCloud -ErrorAction Stop;Throw "This runbook must be run on-premises via Hybrid Runbook Worker. Exiting."} Catch {}
The variable $AmIInAzure is simply used to hide the output of Get-AzureRMEnvironment, while the Try..Catch is to hide any errors. If this code is run in Azure, it will throw the specified text and the runbook will error out (as desired). If it is run on a hybrid worker, it doesn't do anything (allowing the rest of the runbook to run).
I'm curious if anyone might have a better method.
Update 2: That oneliner doesn't seem to work, as neither throw, exit, or break will cause the runbook to exit. Still looking for a working method...
You could test using $PSPrivateMetadata
begin {
if ($null -eq $PSPrivateMetadata) {
throw "This command can only be run within the context of an Azure Automation Runbook Worker"
}
}
I had the exact same problem and did not get it to work.
Ended up with another solution, I´m just running this at the top of my runbook, or directly after my param list if you have input parameters.
$checkHybridWorker = hostname
if ($checkHybridWorker -ne "myhybridworkerhostname"){
Write-Warning "Job must be started from Hybrid worker, exiting."
Exit 1
}
Not pretty but it works fine.

Resources