Skip to content
Daniel Berger edited this page Apr 3, 2020 · 7 revisions

Capturing An Image

If you want to capture an image that you can use for future provisioning, then you will need to capture it. This requires a series of steps.

For our example, we'll assume that you've provisioned a Windows VM and that it's currently running.

Get the winrm gem

We'll need to run sysprep on the VM before we begin. Because this is a Windows VM, we'll need to use the winrm gem to run a command remotely.

You could, of course, use Microsoft Remote Desktop instead and do this manually if you prefer. In fact, winrm may not be enabled by default, depending on the type of VM that you've provisioned.

gem install winrm

With that installed, connect and run sysprep. This will automatically shutdown the VM upon completion, and may take a few minutes.

require 'winrm'

options = {
  :endpoint          => 'http://1.2.3.4:5985/wsman' # Put actual IP here
  :user              => 'foo\Administrator' # Or whomever
  :password          => 'xxx' # Put real password here
  :operation_timeout => 1800
}

# Your exact options may vary
connection = WinRM::Connection.new(options)

script = '$Env:SystemRoot\system32\sysprep\sysprep.exe /generalize /oobe /shutdown'

connection.create_executor do |exec|
  output = shell.run(script)

  if output.stderr && output.stderr.size > 0
    puts "OOPS: #{output.stderr}"
  else
    puts "RESULT: #{output.stdout.strip}"
  end
end

For a Linux VM, ssh into the VM using net-ssh or the command line, and run the following:

sudo waagent -deprovision+user -force

Setup credentials

You'll need to setup your credentials with a tenant ID, client ID, and client key. If you have more than one subscription associated with your tenant, I recommend specifying the subscription ID as well.

require 'azure-armrest'

conf = Azure::Armrest::ArmrestService.configure(
  :client_id       => 'xxx',
  :client_key      => 'yyy',
  :tenant_id       => 'zzz',
  :subscription_id => 'xxx'
)

Deallocate the VM

First we'll need to deallocate the virtual machine

vms = Azure::Armrest::VirtualMachineService.new(conf)

your_vm   = 'your-winimg'
res_group = 'your_resource_group'

vms.deallocate(windows_vm, res_group)

Using the CLI you would do this:

az vm deallocate -n your_vm -g your_group

Generalize the VM

Once the VM is deallocated, we need to first generalize it, i.e. make it suitable as an image that other VM's can then be provisioned from:

vms.generalize(windows_vm, res_group)

Create the Image

If the VM you created is unmanaged (i.e. using unmanaged storage), then create an image using the capture method like so:

# Note that you can write these options like 'vhdPrefix' or 'vhd_prefix', as you choose
options = {
  :vhdPrefix => "test-win2k12-img", # Or whatever
  :destinationContainerName => "your-test-container",
  :overwriteVhds => true
}

vms.capture(your_vm, options, res_group)

If the VM you created is managed (most likely), then you will need to create an image using a different service:

ims = Azure::Armrest::Storage::ImageService.new(conf)
vm = vms.get(your_vm, res_group)

options = {
  :location => 'West US',
  :properties => {
    :source_virtual_machine => {:id => vm.id}
  }
}

ims.create(name, group, options)

Using the CLI for a managed VM:

az image create -n your-vm-img -g your-group --source your-vm

View it

For unmanaged images, your captured image now resides in the storage account as a blob. You can view it in the portal under Blob service -> system -> Microsoft.Compute -> Images -> your-test-container.

You can also see it using the armrest gem like so:

sas = Azure::Armrest::StorageAccountService.new(conf)
storage_acct_name = 'your_storage_acct'
p sas.list_private_images(res_group)

For managed images, you can see a list of images using the Azure::Armrest::Storage::ImageService instance we created earlier:

p ims.list_all

More Reading

This documentation basically follows this blog post: http://www.codeisahighway.com/how-to-capture-your-own-custom-virtual-machine-image-under-azure-resource-manager-api/

See also: https://docs.microsoft.com/en-us/azure/virtual-machines/linux/tutorial-custom-images