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

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)

Generalize and Capture 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, then capture it.

vms.generalize(windows_vm, res_group)

options = {
  :vhdPrefix => "test-win2k12-img", # Or whatever
  :destinationContainerName => "your-test-container",
  :overwriteVhds => true
}

vms.capture(your_vm, options, res_group)

View it

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)

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/