3
votes

I'm using azure-sdk-for-python to create and delete VMs.

https://github.com/Azure/azure-sdk-for-python

http://azure-sdk-for-python.readthedocs.io/en/latest/

I've successfully managed to write the code to create and delete my VMs using the resource manager approach (not the classic).

The basic to create a VM can be seen here: http://azure-sdk-for-python.readthedocs.io/en/latest/resourcemanagementcomputenetwork.html

I'm not worried about deleting the resource group and the storage account, as I'm using the same for all my VMs.

To delete a the created VM I have something like this:

# 1. Delete the virtual machine
result = compute_client.virtual_machines.delete(
    group_name,
    vm_name            
)
result.wait()
# 2. Delete the network interface
result = network_client.network_interfaces.delete(
    group_name,
    network_interface_name
)
result.wait()
# 3. Delete the ip
result = network_client.public_ip_addresses.delete(
    group_name,
    public_ip_address_name
)
result.wait()

As some know the data disks are not deleted along with its VM. I know it can be done with the Azure CLI: https://azure.microsoft.com/en-us/documentation/articles/storage-azure-cli/

azure storage blob delete -a <storage_account_name> -k <storage_account_key> -q vhds <data_disk>.vhd

But I don't know how to do it programmatically with azure-sdk-for-python. And I didn't want to depend on the Azure CLI as the rest of my code is using the python sdk.

I would appreciate some help on how to do it.

Thanks

4

4 Answers

1
votes

You can leverage the Azure ComputeManagementClient's disks APIs to obtain list of disks associated with a VM and then iterate over them to delete the disks. Here's some sample code to achieve the same:

def delete_vm(self, vm_name, nic_name, group_name):
    # Delete VM
    print('Delete VM {}'.format(vm_name))
    try:
        async_vm_delete = self.compute_client.virtual_machines.delete(group_name, vm_name)
        async_vm_delete.wait()
        net_del_poller = self.network_client.network_interfaces.delete(group_name, nic_name)
        net_del_poller.wait()
        disks_list = self.compute_client.disks.list_by_resource_group(group_name)
        disk_handle_list = []
        for disk in disks_list:
            if vm_name in disk.name:
                async_disk_delete = self.compute_client.disks.delete(self.group_name, disk.name)
                async_disk_handle_list.append(async_disk_delete)
        print("Queued disks will be deleted now...")
        for async_disk_delete in disk_handle_list:
                async_disk_delete.wait()
    except CloudError:
        print('A VM delete operation failed: {}'.format(traceback.format_exc()))
        return False
    print("Deleted VM {}".format(vm_name))
    return True
0
votes

You can use the Storage Management SDK to get the storage_account_key without writing it explicitly: http://azure-sdk-for-python.readthedocs.io/en/latest/resourcemanagementstorage.html#get-storage-account-keys

To delete a VHD inside a storage account, you have to use the Storage Data SDK here: https://github.com/Azure/azure-storage-python

You have samples in the "samples" folder or here: https://github.com/Azure-Samples/storage-python-getting-started

Hope it helps :)

0
votes

Here's a little more code:

storage_account = <name of storage account>

storage_client = StorageManagementClient(...)

keys = storage_client.storage_accounts.list_keys(...)

for key in keys.keys:
    # Use the first key; adjust accordingly if your set up is different
    break

block_blob_service = BlockBlobService(
    account_name=storage_account, account_key=key.value)

for blob in block_blob_service.list_blobs(container):
    print blob.name

I hope you find this useful. Thanks to Laurent for the pointers.

0
votes

To delete the OS disk, one simple way to achieve this is to query for the OS disk name before deleting the VM, and deleting the OS disk after the VM is deleted.

Here is my version of a function that deletes the VM alongside network and storage resources:

def az_delete_vm(resource_group_name, vm_name, delete_os_storage=True, remove_default_network=True):

    os_disk_name = None
    if delete_os_storage:
        vm = compute_client.virtual_machines.get(resource_group_name, vm_name)
        os_disk_name = vm.storage_profile.os_disk.name

    logger.info("Deleting VM %s", vm_name)
    delete_op1 = compute_client.virtual_machines.delete(
        resource_group_name, vm_name)
    delete_op1.wait()

    if delete_os_storage:
        delete_op2 = compute_client.disks.delete(resource_group_name, os_disk_name)
        delete_op2.wait()

    if remove_default_network:
        logger.info("Removing VM network components")
        vnet_name = "{}-vnet".format(vm_name)
        subnet_name = "{}-subnet".format(vm_name)
        nic_name = "{}-nic".format(vm_name)
        public_ip_name = "{}-public-ip".format(vm_name)

        logger.debug("Removing NIC %s", nic_name)
        delete_op3 = network_client.network_interfaces.delete(resource_group_name, nic_name)
        delete_op3.wait()

        # logger.debug("Removing subnet %s", subnet_name)
        # network_client.subnets.delete(resource_group_name, subnet_name)

        logger.debug("Removing vnet %s", vnet_name)
        delete_op4 = network_client.virtual_networks.delete(resource_group_name, vnet_name)

        logger.debug("Removing public IP %s", public_ip_name)
        delete_op5 = network_client.public_ip_addresses.delete(resource_group_name, public_ip_name)

        delete_op4.wait()
        delete_op5.wait()

    logger.info("Done deleting VM")