I\'m hoping to manage some Azure resources using a scheduled C# Azure Function.
Currently in a command line application I\'ve made, I\'ve been using libraries \'Micr
There are a few resources online on using C# to make REST API calls to start and stop a VM. Here's a link to such a document:
https://msftstack.wordpress.com/2016/01/03/how-to-call-the-azure-resource-manager-rest-api-from-c/
You could use the above as a reference to create C# Functions to start/stop your VM.
However, using C# to make these REST calls requires pre-packaging the HTTP request and post processing the HTTP response. If your use-case just calls for a start/stop VM, an easier approach would be use PowerShell in Azure Functions to call the Start-AzureRmVM
and Stop-AzureRmVM
cmdlets.
The following are steps on how to create HTTP-triggered PowerShell Functions to start and stop a VM:
Setup a service principal to obtain the username, password and tenant id. This initial setup may be considered tedious by some users, but since it's a one-time task, I feel that it is worth it to leverage running Azure PowerShell in Functions. There are many docs online, but here are some links to documents on how to setup your service principal:
i. http://blog.davidebbo.com/2014/12/azure-service-principal.html (I used this one)
ii. https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal
Log into the Functions portal to access your Function app.
Click on Function app settings->Configure app settings and add the key-value pairs for the settings SP_USERNAME
, SP_PASSWORD
, and TENANTID
(You may use other desired key names).
Create an HTTP-triggered PowerShell Function named, e.g. StartVm with the following content in its run.ps1
file.
$requestBody = Get-Content $req -Raw | ConvertFrom-Json # Set Service Principal credentials # SP_PASSWORD, SP_USERNAME, TENANTID are app settings $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = Get-AzureRmContext; Set-AzureRmContext -Context $context; # Start VM Start-AzureRmVM -ResourceGroupName $requestBody.resourcegroup -Name $requestBody.vmname | Out-String
Click on the Save button.
Next, click on the Logs button to open the log viewer.
Click on the Test button to open the simple HTTP client. In the request body, provide the vmname and resourcegroup values for the VM, e.g.
{ "vmname": "testvm", "resourcegroup": "testresourcegroup" }
Start-AzureRmVM
cmdlet to run to completion. When it does, you should see similar entries in the log viewer.2016-11-30T07:11:26.479 Function started (Id=1e38ae2c-3cca-4e2f-a85d-f62c0d565c34) 2016-11-30T07:11:28.276 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-11-30T07:11:28.276 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-11-30T07:11:59.312 RequestId IsSuccessStatusCode StatusCode ReasonPhrase --------- ------------------- ---------- ------------ True OK OK 2016-11-30T07:11:59.327 Function completed (Success, Id=1e38ae2c-3cca-4e2f-a85d-f62c0d565c34)
run.ps1
file. If the execution succeeds, the log output should be similar to the log entries for the StartVm Function.$requestBody = Get-Content $req -Raw | ConvertFrom-Json # Set Service Principal credentials # SP_PASSWORD, SP_USERNAME, TENANTID are app settings $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = Get-AzureRmContext; Set-AzureRmContext -Context $context; # Stop VM Stop-AzureRmVM -ResourceGroupName $requestBody.resourcegroup -Name $requestBody.vmname -Force | Out-String
run.ps1
file to verify that the VM has indeed been stopped.$requestBody = Get-Content $req -Raw | ConvertFrom-Json # Set Service Principal credentials # SP_PASSWORD, SP_USERNAME, TENANTID are app settings $secpasswd = ConvertTo-SecureString $env:SP_PASSWORD -AsPlainText -Force; $mycreds = New-Object System.Management.Automation.PSCredential ($env:SP_USERNAME, $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant $env:TENANTID -Credential $mycreds; $context = Get-AzureRmContext; Set-AzureRmContext -Context $context; # Get VM Get-AzureRmVM -ResourceGroupName $requestBody.resourcegroup -Name $requestBody.vmname -Status | Out-String
The log entries for the GetVM Function on a stopped VM will would be similar to the following:
2016-11-30T07:53:59.956 Function started (Id=1841757f-bbb8-45cb-8777-80edb4e75ced) 2016-11-30T07:54:02.040 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-11-30T07:54:02.040 Microsoft.Azure.Commands.Profile.Models.PSAzureContext 2016-11-30T07:54:02.977 ResourceGroupName : testresourcegroup Name : testvm BootDiagnostics : ConsoleScreenshotBlobUri : https://teststorage.blob.core.windows.net/boot diagnostics-vmtest-[someguid]/testvm.[someguid].screenshot.bmp Disks[0] : Name : windowsvmosdisk Statuses[0] : Code : ProvisioningState/succeeded Level : Info DisplayStatus : Provisioning succeeded Time : 11/30/2016 7:15:15 AM Extensions[0] : Name : BGInfo VMAgent : VmAgentVersion : Unknown Statuses[0] : Code : ProvisioningState/Unavailable Level : Warning DisplayStatus : Not Ready Message : VM Agent is unresponsive. Time : 11/30/2016 7:54:02 AM Statuses[0] : Code : ProvisioningState/succeeded Level : Info DisplayStatus : Provisioning succeeded Time : 11/30/2016 7:15:15 AM Statuses[1] : Code : PowerState/deallocated Level : Info DisplayStatus : VM deallocated 2016-11-30T07:54:02.977 Function completed (Success, Id=1841757f-bbb8-45cb-8777-80edb4e75ced)
Note: FYI, while you may write a Function to create a VM by calling the New-AzureRmVM
cmdlet, it will not run to completion in Azure Functions. VM creation in Azure Function's infrastructure seem to take ~9 mins to complete but a Function's execution is terminated at 5 minutes. You may write another script to poll the results separately. This limitation will be lifted when we start supporting custom configuration for maximum execution time in one of our upcoming releases.
--Update-- I just realized you were trying to create scheduled Functions. In that case, you can use Timer-triggered PowerShell Functions and hard-code the vmname and resourcegroup.
Well, I don't really understand how do you expect to authenticate without authenticating, I guess your only option would be certificates?
https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-daemon-certificate-credential/