Architecture Azure Functions
User / Script / Curl
│
▼
HTTP Request
Azure Function (HTTP Trigger)
│
▼
Managed Identity
│
▼
Azure Compute API
│
▼
Filter VMs by Tag
│
┌──────┴────────┐
▼ ▼
Start VM Stop VM
Prerequisites
-
Python 3.9+
-
Visual Studio Code
-
Azure Functions Core Tools
-
Azure CLI
VS Code Extensions:
-
Azure Functions extension for Visual Studio Code
-
Python extension for Visual Studio Code
Requirements
- Enable Managed Identity on Function App.
- Assign Role: Virtual Machine Contributor
requirements.txt
azure-functions
azure-identity
azure-mgmt-compute
azure-mgmt-resource
Folder Structure
vm-control-function
│
├── VMControl
│ ├── __init__.py
│ ├── function.json
│
├── requirements.txt
function.json
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["get", "post"],
"route": "vm-control"
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
init.py
import logging
import os
import azure.functions as func
from azure.identity import DefaultAzureCredential
from azure.mgmt.compute import ComputeManagementClient
from azure.mgmt.resource import ResourceManagementClient
SUBSCRIPTION_ID = os.environ["AZURE_SUBSCRIPTION_ID"]
TAG_NAME = "AutoManage"
TAG_VALUE = "true"
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info("HTTP trigger VM start/stop function")
action = req.params.get("action")
if not action:
return func.HttpResponse(
"Please pass action=start or action=stop",
status_code=400
)
credential = DefaultAzureCredential()
compute_client = ComputeManagementClient(
credential,
SUBSCRIPTION_ID
)
resource_client = ResourceManagementClient(
credential,
SUBSCRIPTION_ID
)
results = []
for rg in resource_client.resource_groups.list():
for vm in compute_client.virtual_machines.list(rg.name):
if vm.tags:
if TAG_NAME in vm.tags and vm.tags[TAG_NAME].lower() == TAG_VALUE:
vm_name = vm.name
if action == "start":
compute_client.virtual_machines.begin_start(
rg.name,
vm_name
)
results.append(f"Started VM: {vm_name}")
elif action == "stop":
compute_client.virtual_machines.begin_deallocate(
rg.name,
vm_name
)
results.append(f"Stopped VM: {vm_name}")
return func.HttpResponse(
"\n".join(results),
status_code=200
)
tag
- ex: AutoManage = true
