This repository has been archived on 2026-07-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
azuredatastudio/extensions/asde-deployment/notebooks/edge/deploy-sql-edge-azure.ipynb
T

26 KiB

Microsoft

Deploy Azure SQL Edge to an Azure VM via IoT hub

This notebook will walk you through the end to end setup of Azure SQL Edge.

  1. Create an Azure Edge VM as a virtual IoT device, you can go the "Default Settings" cell and adjust the vm_size variable based on your needs. Available sizes and pricing information can be found here.
  2. Create an Azure IoT hub, you can go to the "Default Settings" cell and adjust value of the following variables based on your needs: iot_hub_sku and iot_hub_units. Available SKUs and pricing information can be found here.
  3. Add the device to the IoT hub
  4. Deploy SQL Edge module to the device with optional package file
  5. Enable connecting to the SQL Edge instance on the device

Dependencies

Please press the "Run all" button to run the notebook

Check dependencies

In [ ]:
import sys,os,json,html,getpass,time,ntpath,uuid

def run_command(command:str, displayCommand:str = "", returnObject:bool = False):
    print("Executing: " + (displayCommand if displayCommand != "" else command))
    if returnObject:
        output = os.popen(command).read()
        print(f'Command successfully executed')
        return json.loads(''.join(output))
    else:
        !{command}
        if _exit_code != 0:
            sys.exit(f'Command execution failed with exit code: {str(_exit_code)}.\n')
        else:
            print(f'Command successfully executed')

run_command(command='az --version')

Install Azure IoT extension for Azure CLI

In [ ]:
extensions = run_command('az extension list', returnObject=True)
extensions = [ext for ext in extensions if ext['name'] == 'azure-cli-iot-ext']
if len(extensions) > 0:
    run_command('az extension remove --name azure-cli-iot-ext')
run_command('az extension add --name azure-iot')

Required information

In [ ]:
azure_subscription_id = os.environ["AZDATA_NB_VAR_ASDE_SUBSCRIPTIONID"]
azure_resource_group = os.environ["AZDATA_NB_VAR_ASDE_RESOURCEGROUP"]
azure_location = os.environ["AZDATA_NB_VAR_ASDE_AZURE_LOCATION"]
sa_password = os.environ["AZDATA_NB_VAR_SA_PASSWORD"]
vm_admin = os.environ["AZDATA_NB_VAR_ASDE_VM_ADMIN"]
vm_password = os.environ["AZDATA_NB_VAR_ASDE_VM_PASSWORD"]
package_path = os.environ["AZDATA_NB_VAR_ASDE_PACKAGE_PATH"]
sql_port = os.environ["AZDATA_NB_VAR_ASDE_SQL_PORT"]
new_rg_flag = os.environ["AZDATA_NB_VAR_ASDE_NEW_RESOURCEGROUP"]
new_rg_name = os.environ["AZDATA_NB_VAR_ASDE_NEW_RESOURCEGROUP_NAME"]

if new_rg_flag == 'true':
    azure_resource_group = new_rg_name
print(f'Subscription: {azure_subscription_id}')
print(f'Resource group: {azure_resource_group}')
print(f'Location: {azure_location}')
print(f'VM admin username: {vm_admin}')
print(f'VM admin password: ******')
print(f'SQL Server port: {sql_port}')
print(f'SQL Server sa password: ******')
print(f'Package path: {package_path}')

Default settings

In [ ]:
suffix = time.strftime("%y%m%d%H%M%S", time.localtime())
iot_hub_name = f'hub{suffix}'
iot_hub_sku = 'S1'
iot_hub_units = 4
iot_device_id = f'vm{suffix}'
azure_storage_account = f'sa{suffix}'
storage_account_container = 'sqldatabasepackage'
sql_lcid = '1033'
sql_collation = 'SQL_Latin1_General_CP1_CI_AS'
vm_size = 'Standard_DS1_v2'

Login to Azure

In [ ]:
run_command('az login')

Set active Azure subscription

In [ ]:
if azure_subscription_id != "":
    run_command(f'az account set --subscription {azure_subscription_id}')
else:
    print('Using the default Azure subscription', {azure_subscription_id})
run_command(f'az account show')

Create resource group

In [ ]:
rg_exists = run_command(f'az group exists --name {azure_resource_group}', returnObject=True)

if rg_exists:
    print(f'resource group \"{azure_resource_group}\" already exists.')
else:
    run_command(f'az group create --location {azure_location} --name {azure_resource_group}')

Create IoT hub

In [ ]:
hub_list = run_command(f'az iot hub list --resource-group {azure_resource_group}', returnObject=True)
hub_list = [hub for hub in hub_list if hub['name'] == iot_hub_name]
if len(hub_list) == 0:
    run_command(f'az iot hub create --name {iot_hub_name} --resource-group {azure_resource_group} --location {azure_location} --sku {iot_hub_sku} --unit {iot_hub_units}')
else:
    print(f'IoT hub \"{iot_hub_name}\" already exists')

Create storage account and storage account container, then upload the package

In [ ]:
storage_account_created = False
if package_path == "":
    print(f'Package file not provided')
    blob_sas = ''
else:    
    package_name = ntpath.basename(package_path)
    storage_accounts = run_command(f'az storage account list --resource-group {azure_resource_group} --subscription {azure_subscription_id}', returnObject=True)
    storage_accounts = [storage_account for storage_account in storage_accounts if storage_account['name'] == azure_storage_account]
    if len(storage_accounts) == 0:
        storage_account_created = True
        run_command(f'az storage account create -n {azure_storage_account} -g {azure_resource_group} -l {azure_location} --sku Standard_LRS --kind Storage')
    else:
        print(f'storage account \"{azure_storage_account}\" already exists.')

    storage_account_key = run_command(f'az storage account keys list --account-name {azure_storage_account} --resource-group {azure_resource_group}', returnObject=True)[0]['value']
    container_exists = run_command(f'az storage container exists --name {storage_account_container} --account-key {storage_account_key} --account-name {azure_storage_account} --auth-mode key --output json', returnObject=True)['exists']
    if container_exists:
        print(f'storage account container \"{storage_account_container}\" already exists.')
    else:
        run_command(f'az storage container create --name {storage_account_container} --account-key {storage_account_key} --account-name {azure_storage_account} --auth-mode key')

    blob_exists = run_command(f'az storage blob exists --container-name {storage_account_container} --name \"{package_name}\" --account-key {storage_account_key} --account-name {azure_storage_account} --auth-mode key', returnObject=True)['exists']
    if blob_exists:
        print(f'blob \"{package_name}\" already exists.')
    else:
        run_command(f'az storage blob upload --account-name {azure_storage_account} --container-name {storage_account_container} --name {package_name} --file \"{package_path}\" --account-key {storage_account_key} --auth-mode key')
    now = time.localtime()
    expiry = f'{(now.tm_year + 1)}-{now.tm_mon}-{now.tm_mday}'
    blob_sas = run_command(f'az storage blob generate-sas --container-name {storage_account_container} --name \"{package_name}\" --account-name {azure_storage_account} --account-key {storage_account_key} --auth-mode key --full-uri --https-only --permissions r --expiry {expiry}', returnObject=True)

Add the Edge device to the IoT hub

In [ ]:
device_list = run_command(f'az iot hub device-identity list --edge-enabled true --hub-name {iot_hub_name} --resource-group {azure_resource_group}', returnObject=True)
device_list = [device for device in device_list if device['deviceId'] == iot_device_id]
if len(device_list) == 0:
    run_command(f'az iot hub device-identity create --device-id {iot_device_id} --hub-name {iot_hub_name} --resource-group {azure_resource_group} --edge-enabled true')
else:
    print(f'Edge device \"{iot_device_id}\" already exists.')
connection_string = run_command(f'az iot hub device-identity show-connection-string --device-id {iot_device_id} --hub-name {iot_hub_name} --resource-group {azure_resource_group}', returnObject=True)
connection_string = connection_string['connectionString']

Create an Edge enabled VM as an Edge device

In [ ]:
iot_deploy_result = run_command((f"az deployment group create "
f"--resource-group {azure_resource_group} "
f"--template-uri \"https://aka.ms/iotedge-vm-deploy\" "
f"--parameters vmSize={vm_size} "
f"--parameters dnsLabelPrefix={iot_device_id} "
f"--parameters adminUsername={vm_admin} "
f"--parameters deviceConnectionString={connection_string} "
f"--parameters authenticationType=password "
f"--parameters adminPasswordOrKey=\"{vm_password}\""), returnObject=True)
vm_resource = [resource for resource in iot_deploy_result['properties']['dependencies'] if resource['resourceType'] == 'Microsoft.Compute/virtualMachines']
if len(vm_resource) != 1:
    sys.exit('Failed to deploy the IoT Edge VM')
vm_name = vm_resource[0]['resourceName']
nsg_name = vm_name.replace('vm-','nsg-')
ip_address = run_command(f'az vm show -d -g {azure_resource_group} -n {vm_name} --query publicIps', returnObject=True)
run_command(f'az network nsg rule create --name \"SQL\" --nsg-name {nsg_name} --priority 100 --resource-group {azure_resource_group} --access Allow --description \"Allow SQL\" --destination-address-prefixes \"*\" --destination-port-ranges {sql_port} --direction Inbound --source-address-prefixes Internet --protocol Tcp')

Deploy Azure SQL Edge to the device

In [ ]:
manifest = '{\"modulesContent\":{\"$edgeAgent\":{\"properties.desired\":{\"modules\":{\"AzureSQLEdge\":{\"settings\":{\"image\":\"mcr.microsoft.com/azure-sql-edge\",\"createOptions\":\"{\\\"HostConfig\\\":{\\\"CapAdd\\\":[\\\"SYS_PTRACE\\\"],\\\"Binds\\\":[\\\"sqlvolume:/sqlvolume\\\"],\\\"PortBindings\\\":{\\\"1433/tcp\\\":[{\\\"HostPort\\\":\\\"<SQL_Port>\\\"}]},\\\"Mounts\\\":[{\\\"Type\\\":\\\"volume\\\",\\\"Source\\\":\\\"sqlvolume\\\",\\\"Target\\\":\\\"/var/opt/mssql\\\"}]},\\\"User\\\":\\\"0:0\\\",\\\"Env\\\":[\\\"MSSQL_AGENT_ENABLED=TRUE\\\",\\\"ClientTransportType=AMQP_TCP_Only\\\",\\\"PlanId=asde-developer-on-iot-edge\\\"]}\"},\"type\":\"docker\",\"version\":\"1.0\",\"env\":{\"ACCEPT_EULA\":{\"value\":\"Y\"},\"SA_PASSWORD\":{\"value\":\"<Default_SQL_SA_Password>\"},\"MSSQL_LCID\":{\"value\":\"<SQL_LCID>\"},\"MSSQL_COLLATION\":{\"value\":\"<SQL_Collation>\"}<PACKAGE_INFO>},\"status\":\"running\",\"restartPolicy\":\"always\"}},\"runtime\":{\"settings\":{\"minDockerVersion\":\"v1.25\"},\"type\":\"docker\"},\"schemaVersion\":\"1.0\",\"systemModules\":{\"edgeAgent\":{\"settings\":{\"image\":\"mcr.microsoft.com/azureiotedge-agent:1.0\",\"createOptions\":\"\"},\"type\":\"docker\"},\"edgeHub\":{\"settings\":{\"image\":\"mcr.microsoft.com/azureiotedge-hub:1.0\",\"createOptions\":\"{\\\"HostConfig\\\":{\\\"PortBindings\\\":{\\\"443/tcp\\\":[{\\\"HostPort\\\":\\\"443\\\"}],\\\"5671/tcp\\\":[{\\\"HostPort\\\":\\\"5671\\\"}],\\\"8883/tcp\\\":[{\\\"HostPort\\\":\\\"8883\\\"}]}}}\"},\"type\":\"docker\",\"status\":\"running\",\"restartPolicy\":\"always\"}}}},\"$edgeHub\":{\"properties.desired\":{\"routes\":{},\"schemaVersion\":\"1.0\",\"storeAndForwardConfiguration\":{\"timeToLiveSecs\":7200}}},\"AzureSQLEdge\":{\"properties.desired\":{\"ASAJobInfo\":\"<Optional_ASA_Job_SAS_URL>\"}}}}'
package_info = '' if blob_sas == ''else ',\"MSSQL_PACKAGE\":{\"value\":\"'+blob_sas+'\"}'
manifest = manifest.replace('<PACKAGE_INFO>', package_info).replace('<Default_SQL_SA_Password>',sa_password).replace('<SQL_LCID>',sql_lcid).replace('<SQL_Port>',sql_port).replace('<SQL_Collation>',sql_collation)
file_name = f'{uuid.uuid4().hex}.json'
manifest_file = open(file_name, 'w')
manifest_file.write(manifest)
manifest_file.close()
run_command(f'az iot edge set-modules --device-id \"{iot_device_id}\" --hub-name \"{iot_hub_name}\" --content \"{file_name}\" --resource-group {azure_resource_group}')
os.remove(file_name)

Connect to Azure SQL Edge instance in Azure Data Studio

Click the link below to connect to the Azure SQL Edge instance, it might take a couple minutes for the service to start.

In [ ]:
from IPython.display import *
connectionParameter = '{"serverName":"' + f'{ip_address},{sql_port}' + '","providerName":"MSSQL","authenticationType":"SqlLogin","userName": "sa","password":' + json.dumps(sa_password) + ',"options": {"trustServerCertificate":true}}'
display(HTML('<br/><a href="command:azdata.connect?' + html.escape(connectionParameter)+'"><font size="3">Click here to connect to the Azure SQL Edge instance</font></a><br/>'))
display(HTML('<br/><span style="color:red"><font size="2">NOTE: The Azure SQL Edge instance password is included in this link, you may want to clear the results of this code cell before saving the notebook.</font></span>'))
In [ ]:
if storage_account_created:
    delete_storage_account_command = "run_command(f'az storage account delete -n {azure_storage_account} -g {azure_resource_group} --yes')"
    display(HTML('<span style="color:red"><font size="2">NOTE: A storage account was created to host the package file, you can delete it after the database is created and populated successfully. To delete the storage account, copy the following code to a new code cell and run the cell.</font></span>'))
    display(HTML('<span><font size="2">'+delete_storage_account_command+'</font></span>'))