azureazure-sdk-js

Azure HyperVGeneration V2 VM creation


I'm looking to spin up VMs using the node/Javascript SDK for Azure. So far I've had luck with my code and it pretty much works as expected. However I would like to spin up generation 2 / HyperV v2 VMs instead of the default v1. Here's a snippet of my code:

return new Promise((resolve, reject) => {
    let resourceClient = new ComputeManagementClient(credentials, azureSubscriptionID);
    resourceClient.virtualMachines.createOrUpdate(reourceGroup, name, {
      location: location,
      osProfile: { computerName: name, adminUsername: 'admin', adminPassword: adminPassword, customData: Buffer.from(prepScript).toString('base64') },
      hardwareProfile: { vmSize: 'Standard_B2s' },
      HyperVGeneration: 'V2',
      storageProfile: {
        imageReference: { publisher: 'Canonical', offer: 'UbuntuServer', sku: '18.04-LTS', version: 'latest' },
        osDisk: { name: name + '-disk', createOption: 'FromImage' }
      },
      networkProfile: {
        networkInterfaces: [{ id: nic.id, primary: true }]
      }
    }, function (err, result) {
      if (err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  }

The problem I'm having is with:

HyperVGeneration: 'V2'

as it seems to not even apply. Nor do I get any errors, just a V1 VM is created. The Azure Docs are kind of lacking here: https://learn.microsoft.com/en-us/javascript/api/@azure/arm-compute/hypervgeneration?view=azure-node-latest I've also tried the other parameters such as HyperVGenerationType / Types with the same result.


Solution

  • I figured it out!

    I was working off the wrong assumption here. Instead of configuring the VM generation/HyperVGeneration to V2, somehow using a gen2 image sku to base the OS disk off of, automatically configures the VM generation to V2 as well. It also doesn't help the fact that MS calls the same thing by multiple names: VM generation, HyperV generation, image generation.

    Anyway the solution is to actually look up all available images which can be installed and pick the correct one from there. To get available images for your region:

    az vm image list --all --publisher 'Canonical' --sku '18_04' --output table
    

    Which returns something like:

    Offer                                         Publisher    Sku                           Urn                                                                                          Version
    --------------------------------------------  -----------  ----------------------------  -------------------------------------------------------------------------------------------  ---------------
    0001-com-ubuntu-confidential-vm-experimental  Canonical    18_04                         Canonical:0001-com-ubuntu-confidential-vm-experimental:18_04:18.04.20210309                  18.04.20210309
    0001-com-ubuntu-confidential-vm-experimental  Canonical    18_04-gen2                    Canonical:0001-com-ubuntu-confidential-vm-experimental:18_04-gen2:18.04.20210309             18.04.20210309
    0001-com-ubuntu-pro-advanced-sla              Canonical    18_04                         Canonical:0001-com-ubuntu-pro-advanced-sla:18_04:18.04.20200318                              18.04.20200318
    0001-com-ubuntu-pro-advanced-sla              Canonical    18_04                         Canonical:0001-com-ubuntu-pro-advanced-sla:18_04:18.04.20200605                              18.04.20200605
    ...
    

    Another thing of note is that some Ubuntu images have the sku as "18.04" and some "18_04" which further confuses things.

    The final solution was this use this snippet in order to put it all together:

    return new Promise((resolve, reject) => {
        let resourceClient = new ComputeManagementClient(credentials, azureSubscriptionID);
        resourceClient.virtualMachines.createOrUpdate(reourceGroup, name, {
          location: location,
          osProfile: { computerName: name, adminUsername: 'admin', adminPassword: adminPassword, customData: Buffer.from(prepScript).toString('base64') },
          hardwareProfile: { vmSize: 'Standard_B2s' },
          storageProfile: {
            imageReference: { publisher: 'Canonical', offer: 'UbuntuServer', sku: '18_04-lts-gen2', version: 'latest' },
            osDisk: { name: name + '-disk', createOption: 'FromImage' }
          },
          networkProfile: {
            networkInterfaces: [{ id: nic.id, primary: true }]
          }
        }, function (err, result) {
          if (err) {
            reject(err);
          } else {
            resolve(result);
          }
        });
      }
    

    Notice how the image sku is 18_04-lts-gen2 instead of 18.04-LTS.