2

I am able to create an image via az cli commands with:

az vm create --resource-group $RG2 \
--name $VM_NAME --image $(az sig image-version show \
--resource-group $RG \
--gallery-name $SIG \
--gallery-image-definition $SIG_IMAGE_DEFINITION \
--gallery-image-version $VERSION \
--query id -o tsv) \
--size $SIZE \
--public-ip-address "" \
--assign-identity $(az identity show --resource-group $RG2 --name $IDENTITY --query id -o tsv) \
--ssh-key-values $SSH_KEY_PATH \
--authentication-type ssh \
--admin-username admin

This works great. I am trying to do the same with python.
I see examples where they are creating everything in that, resource groups, nics, subnets, vnets etc but that is not what I need. I am literally trying to do what this az cli is doing. Is there a way to do this with python?

How do we address the setting of public ip to nothing so it does not set one? I want it to use the vnet, subnet, etc that the resource groups already has defined just like the az cli.

2 Answers 2

1

You can modify the example script in our doc to do this. Essentially, you need to get rid of step 4. and modify step 5 to not send a public IP when creating the NIC. This has been validated in my own subscription.

# Import the needed credential and management objects from the libraries.
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ResourceManagementClient
from azure.mgmt.network import NetworkManagementClient
from azure.mgmt.compute import ComputeManagementClient
import os

print(f"Provisioning a virtual machine...some operations might take a minute or two.")

# Acquire a credential object using CLI-based authentication.
credential = AzureCliCredential()

# Retrieve subscription ID from environment variable.
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]


# Step 1: Provision a resource group

# Obtain the management object for resources, using the credentials from the CLI login.
resource_client = ResourceManagementClient(credential, subscription_id)

# Constants we need in multiple places: the resource group name and the region
# in which we provision resources. You can change these values however you want.
RESOURCE_GROUP_NAME = "PythonAzureExample-VM-rg"
LOCATION = "westus2"

# Provision the resource group.
rg_result = resource_client.resource_groups.create_or_update(RESOURCE_GROUP_NAME,
    {
        "location": LOCATION
    }
)


print(f"Provisioned resource group {rg_result.name} in the {rg_result.location} region")

# For details on the previous code, see Example: Provision a resource group
# at https://learn.microsoft.com/azure/developer/python/azure-sdk-example-resource-group


# Step 2: provision a virtual network

# A virtual machine requires a network interface client (NIC). A NIC requires
# a virtual network and subnet along with an IP address. Therefore we must provision
# these downstream components first, then provision the NIC, after which we
# can provision the VM.

# Network and IP address names
VNET_NAME = "python-example-vnet"
SUBNET_NAME = "python-example-subnet"
IP_NAME = "python-example-ip"
IP_CONFIG_NAME = "python-example-ip-config"
NIC_NAME = "python-example-nic"

# Obtain the management object for networks
network_client = NetworkManagementClient(credential, subscription_id)

# Provision the virtual network and wait for completion
poller = network_client.virtual_networks.begin_create_or_update(RESOURCE_GROUP_NAME,
    VNET_NAME,
    {
        "location": LOCATION,
        "address_space": {
            "address_prefixes": ["10.0.0.0/16"]
        }
    }
)

vnet_result = poller.result()

print(f"Provisioned virtual network {vnet_result.name} with address prefixes {vnet_result.address_space.address_prefixes}")

# Step 3: Provision the subnet and wait for completion
poller = network_client.subnets.begin_create_or_update(RESOURCE_GROUP_NAME, 
    VNET_NAME, SUBNET_NAME,
    { "address_prefix": "10.0.0.0/24" }
)
subnet_result = poller.result()

print(f"Provisioned virtual subnet {subnet_result.name} with address prefix {subnet_result.address_prefix}")

# Step 4: Provision an IP address and wait for completion
# Removed as not needed

# Step 5: Provision the network interface client
poller = network_client.network_interfaces.begin_create_or_update(RESOURCE_GROUP_NAME,
    NIC_NAME, 
    {
        "location": LOCATION,
        "ip_configurations": [ {
            "name": IP_CONFIG_NAME,
            "subnet": { "id": subnet_result.id }
        }]
    }
)

nic_result = poller.result()

print(f"Provisioned network interface client {nic_result.name}")

# Step 6: Provision the virtual machine

# Obtain the management object for virtual machines
compute_client = ComputeManagementClient(credential, subscription_id)

VM_NAME = "ExampleVM"
USERNAME = "azureuser"
PASSWORD = "ChangePa$$w0rd24"

print(f"Provisioning virtual machine {VM_NAME}; this operation might take a few minutes.")

# Provision the VM specifying only minimal arguments, which defaults to an Ubuntu 18.04 VM
# on a Standard DS1 v2 plan with a public IP address and a default virtual network/subnet.

poller = compute_client.virtual_machines.begin_create_or_update(RESOURCE_GROUP_NAME, VM_NAME,
    {
        "location": LOCATION,
        "storage_profile": {
            "image_reference": {
                "publisher": 'Canonical',
                "offer": "UbuntuServer",
                "sku": "16.04.0-LTS",
                "version": "latest"
            }
        },
        "hardware_profile": {
            "vm_size": "Standard_DS1_v2"
        },
        "os_profile": {
            "computer_name": VM_NAME,
            "admin_username": USERNAME,
            "admin_password": PASSWORD
        },
        "network_profile": {
            "network_interfaces": [{
                "id": nic_result.id,
            }]
        }        
    }
)

vm_result = poller.result()

print(f"Provisioned virtual machine {vm_result.name}")
Sign up to request clarification or add additional context in comments.

2 Comments

We also want it to use the vnet and subnet already assigned in the resource group instead of making a vnet. What needs to change in that code to do that? It looks like it is expecting in network_profile a nic_result.id. Removing 4 and 5 means there is no nic_result.id. Note that we are trying also to use an image instead of latest ubuntu for example.
0
resource_name = f"myserver{random.randint(1000, 9999)}"    
VNET_NAME = "myteam-vpn-vnet"
SUBNET_NAME = "myteam-subnet"
IP_NAME = resource_name + "-ip"
IP_CONFIG_NAME = resource_name + "-ip-config"
NIC_NAME = resource_name + "-nic"

Subnet=network_client.subnets.get(resource_group_name, VNET_NAME, SUBNET_NAME)

# Step 5: Provision the network interface client
poller = network_client.network_interfaces.begin_create_or_update(resource_group_name,
    NIC_NAME, 
    {
        "location": location,
        "ip_configurations": [{
            "name": IP_CONFIG_NAME,
            "subnet": { "id": Subnet.id },
            
        }]
    }
) 
nic_result = poller.result()

Yes, we removed steps 4 and 5 above as suggested. The nic was then applied in the vm creation as such:

"network_profile": {
            "network_interfaces": [
                {
                    "id": nic_result.id
                }
            ]
        },

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.