class Azure::Armrest::VirtualMachineService
Base class for managing virtual machines
Public Class Methods
Create and return a new VirtualMachineService
instance. Most methods for a VirtualMachineService
instance will return one or more VirtualMachine
instances.
This subclass accepts the additional :provider option as well. The default is ‘Microsoft.Compute’. You may need to set this to ‘Microsoft.ClassicCompute’ for your purposes.
Azure::Armrest::ArmrestService::new
# File lib/azure/armrest/virtual_machine_service.rb, line 15 def initialize(configuration, options = {}) super(configuration, 'virtualMachines', 'Microsoft.Compute', options) end
Public Instance Methods
Captures the vmname
and associated disks into a reusable CSM template. The 3rd argument is a hash of options that supports the following keys:
-
vhdPrefix - The prefix in the name of the blobs.
-
destinationContainerName - The name of the container inside which the image will reside.
-
overwriteVhds - Boolean that indicates whether or not to overwrite any VHD’s
with the same prefix. The default is false.
# File lib/azure/armrest/virtual_machine_service.rb, line 55 def capture(vmname, options, group = configuration.resource_group) vm_operate('capture', vmname, group, options) end
Stop the VM vmname
in group
and deallocate the tenant in Fabric.
# File lib/azure/armrest/virtual_machine_service.rb, line 61 def deallocate(vmname, group = configuration.resource_group) vm_operate('deallocate', vmname, group) end
Delete the VM and associated resources. By default, this will delete the VM, its NIC, the associated IP address, and the image files (.vhd and .status) for the VM.
If you want to delete other associated resources, such as any attached disks, the VM’s underlying storage account, or associated network security groups you must explicitly specify them as an option.
An attempt to delete a resource that cannot be deleted because it’s still associated with some other resource will be logged and skipped.
If the :verbose option is set to true, then additional messages are sent to your configuration log, or stdout if no log was specified.
Note that if all of your related resources are in a self-contained resource group, you do not necessarily need this method. You could just delete the resource group itself, which would automatically delete all of its resources.
# File lib/azure/armrest/virtual_machine_service.rb, line 175 def delete_associated_resources(vmname, vmgroup, options = {}) options = { :network_interfaces => true, :ip_addresses => true, :os_disk => true, :data_disks => false, :network_security_groups => false, :storage_account => false, :verbose => false }.merge(options) Azure::Armrest::Configuration.log ||= STDOUT if options[:verbose] vm = get(vmname, vmgroup) delete_and_wait(self, vmname, vmgroup, options) # Must delete network interfaces first if you want to delete # IP addresses or network security groups. if options[:network_interfaces] || options[:ip_addresses] || options[:network_security_groups] delete_associated_nics(vm, options) end if options[:os_disk] || options[:storage_account] delete_associated_disk(vm, options) end if options[:data_disks] delete_associated_data_disks(vm, options) end end
Sets the OSState for the vmname
in group
to ‘Generalized’.
# File lib/azure/armrest/virtual_machine_service.rb, line 67 def generalize(vmname, group = configuration.resource_group) vm_operate('generalize', vmname, group) end
Retrieves the settings of the VM named vmname
in resource group group
, which will default to the same as the name of the VM.
You can also specify any query options. At this time only the :expand => ‘instanceView’ option is supported, but others could be added over time.
For backwards compatibility, the third argument may also be a boolean which will retrieve the model view by default. Set to false if you only want the instance view.
Examples:
vms = VirtualMachineService.new(credentials) # Standard call, get just the model view vms.get('some_name', 'some_group') vms.get('some_name', 'some_group', true) # same # Get the instance view only vms.get('some_name', 'some_group', false) # Get the instance view merged with the model view vms.get('some_name', 'some_group', :expand => 'instanceView')
Azure::Armrest::ResourceGroupBasedService#get
# File lib/azure/armrest/virtual_machine_service.rb, line 96 def get(vmname, group = configuration.resource_group, options = {}) if options.kind_of?(Hash) url = build_url(group, vmname, options) response = rest_get(url) VirtualMachineInstance.new(response) else options ? super(vmname, group) : get_instance_view(vmname, group) end end
Convenient wrapper around the get method that retrieves only the instance view for vmname
in resource_group group
.
# File lib/azure/armrest/virtual_machine_service.rb, line 117 def get_instance_view(vmname, group = configuration.resource_group) raise ArgumentError, "must specify resource group" unless group raise ArgumentError, "must specify name of the resource" unless vmname url = build_url(group, vmname, 'instanceView') response = rest_get(url) VirtualMachineInstance.new(response) end
Convenient wrapper around the get method that retrieves the model view for vmname
in resource_group group
without the instance view information.
# File lib/azure/armrest/virtual_machine_service.rb, line 110 def get_model_view(vmname, group = configuration.resource_group) get(vmname, group) end
Return a list of virtual machines for the given location
.
# File lib/azure/armrest/virtual_machine_service.rb, line 21 def list_by_location(location, options = {}) url = url_with_api_version(api_version, base_url, 'providers', provider, 'locations', location, service_name) response = rest_get(url) get_all_results(response, options[:skip_accessors_definition]) end
# File lib/azure/armrest/virtual_machine_service.rb, line 207 def model_class VirtualMachineModel end
Restart the VM vmname
for the given group
, which will default to the same as the vmname.
This is an asynchronous operation that returns a response object which you can inspect, such as response.code or response.headers.
# File lib/azure/armrest/virtual_machine_service.rb, line 132 def restart(vmname, group = configuration.resource_group) vm_operate('restart', vmname, group) end
Return a list of available VM series (aka sizes, flavors, etc), such as “Basic_A1”, though other information is included as well.
# File lib/azure/armrest/virtual_machine_service.rb, line 30 def series(location) namespace = 'microsoft.compute' version = configuration.provider_default_api_version(namespace, 'locations/vmsizes') unless version raise ArgumentError, "Unable to find resources for #{namespace}" end url = url_with_api_version( version, base_url, 'providers', provider, 'locations', location, 'vmSizes' ) JSON.parse(rest_get(url))['value'].map{ |hash| VirtualMachineSize.new(hash) } end
Start the VM vmname
for the given group
, which will default to the same as the vmname.
This is an asynchronous operation that returns a response object which you can inspect, such as response.code or response.headers.
# File lib/azure/armrest/virtual_machine_service.rb, line 142 def start(vmname, group = configuration.resource_group) vm_operate('start', vmname, group) end
Stop the VM vmname
for the given group
gracefully. However, a forced shutdown will occur after 15 minutes.
This is an asynchronous operation that returns a response object which you can inspect, such as response.code or response.headers.
# File lib/azure/armrest/virtual_machine_service.rb, line 152 def stop(vmname, group = configuration.resource_group) vm_operate('powerOff', vmname, group) end
Private Instance Methods
Delete a service
type resource using its name and resource group, and wait for the operation to complete before returning.
If the operation fails because a dependent resource is still attached, then the error is logged (in verbose mode) and ignored.
# File lib/azure/armrest/virtual_machine_service.rb, line 341 def delete_and_wait(service, name, group, options) resource_type = service.class.to_s.sub('Service', '').split('::').last log("Deleting #{resource_type} #{name}/#{group}") if options[:verbose] wait(service.delete(name, group), 0) log("Deleted #{resource_type} #{name}/#{group}") if options[:verbose] rescue Azure::Armrest::BadRequestException, Azure::Armrest::PreconditionFailedException => err if options[:verbose] msg = "Unable to delete #{resource_type} #{name}/#{group}, skipping. Message: #{err.message}" log('warn', msg) end end
This deletes any attached data disks that are associated with the virtual machine. Note that this should only happen after the VM has been deleted.
# File lib/azure/armrest/virtual_machine_service.rb, line 272 def delete_associated_data_disks(vm, options) sds = Azure::Armrest::Storage::DiskService.new(configuration) data_disks = vm.properties.storage_profile.try(:data_disks) data_disks&.each do |data_disk| disk = sds.get_by_id(data_disk.managed_disk.id) delete_and_wait(sds, disk.name, disk.resource_group, options) end end
This deletes the OS disk from the storage account that’s backing the virtual machine, along with the .status file. This does NOT delete copies of the disk.
If the option to delete the entire storage account was selected, then it will not bother with deleting invidual files from the storage account first.
# File lib/azure/armrest/virtual_machine_service.rb, line 260 def delete_associated_disk(vm, options) if vm.managed_disk? delete_managed_storage(vm, options) else delete_unmanaged_storage(vm, options) end end
Deletes any NIC’s associated with the VM, and optionally any public IP addresses and network security groups.
# File lib/azure/armrest/virtual_machine_service.rb, line 216 def delete_associated_nics(vm, options) nis = Azure::Armrest::Network::NetworkInterfaceService.new(configuration) nics = vm.properties.network_profile.network_interfaces.map(&:id) if options[:ip_addresses] ips = Azure::Armrest::Network::IpAddressService.new(configuration) end if options[:network_security_groups] nsgs = Azure::Armrest::Network::NetworkSecurityGroupService.new(configuration) end nics.each do |nic_id_string| nic = get_by_id(nic_id_string) delete_and_wait(nis, nic.name, nic.resource_group, options) if options[:ip_addresses] nic.properties.ip_configurations.each do |ipconfig| address = ipconfig.properties.try(:public_ip_address) if address ip = get_by_id(address.id) delete_and_wait(ips, ip.name, ip.resource_group, options) end end end if options[:network_security_groups] if nic.properties.respond_to?(:network_security_group) nsg = get_by_id(nic.properties.network_security_group.id) delete_and_wait(nsgs, nsg.name, nsg.resource_group, options) end end end end
# File lib/azure/armrest/virtual_machine_service.rb, line 282 def delete_managed_storage(vm, options) sds = Azure::Armrest::Storage::DiskService.new(configuration) disk = sds.get_by_id(vm.properties.storage_profile.os_disk.managed_disk.id) delete_and_wait(sds, disk.name, disk.resource_group, options) end
# File lib/azure/armrest/virtual_machine_service.rb, line 288 def delete_unmanaged_storage(vm, options) sas = Azure::Armrest::StorageAccountService.new(configuration) storage_account = sas.get_from_vm(vm) # Deleting the storage account does not require deleting the disks # first, so skip that if deletion of the storage account was requested. if options[:storage_account] delete_and_wait(sas, storage_account.name, storage_account.resource_group, options) else keys = sas.list_account_keys(storage_account.name, storage_account.resource_group) key = keys['key1'] || keys['key2'] disk = sas.get_os_disk(vm) # There's a short delay between deleting the VM and unlocking the underlying # .vhd file by Azure. Therefore we sleep up to two minutes while checking. if disk.x_ms_lease_status.casecmp('unlocked') != 0 sleep_time = 0 while sleep_time < 120 sleep 10 sleep_time += 10 disk = sas.get_os_disk(vm) break if disk.x_ms_lease_status.casecmp('unlocked') != 0 end # In the unlikely event it did not unlock, just log and skip. if disk.x_ms_lease_status.casecmp('unlocked') != 0 log('warn', "Unable to delete disk #{disk.container}/#{disk.name}") return end end storage_account.delete_blob(disk.container, disk.name, key) log("Deleted blob #{disk.container}/#{disk.name}") if options[:verbose] begin status_file = File.basename(disk.name, '.vhd') + '.status' storage_account.delete_blob(disk.container, status_file, key) rescue Azure::Armrest::NotFoundException # Ignore, does not always exist. else log("Deleted blob #{disk.container}/#{status_file}") if options[:verbose] end end end
# File lib/azure/armrest/virtual_machine_service.rb, line 356 def vm_operate(action, vmname, group, options = {}) raise ArgumentError, "must specify resource group" unless group raise ArgumentError, "must specify name of the vm" unless vmname url = build_url(group, vmname, action) response = rest_post(url, options.to_json) Azure::Armrest::ResponseHeaders.new(response.headers).tap do |headers| headers.response_code = response.code end end