class Azure::VirtualMachineManagement::VirtualMachineManagementService

Private Instance Methods

add_data_disk(vm_name, cloud_service_name, options = {}) click to toggle source

Public: adds a data disk to a virtual machine.

Attributes

  • cloud_service_name - String. Cloud service name.

  • vm_name - String. Virtual machine name.

  • options - Hash. Optional parameters.

Options

Accepted key/value pairs in options parameter are:

  • :import - Boolean. if true, then allows to use an existing

disk by disk name. if false, then create and attach new data disk.
  • :disk_name - String. Specifies the name of the disk. Reqruied if using existing disk.

  • :host_caching - String. Specifies the caching behavior of data disk The default is ReadOnly. Possible values are: None, ReadOnly, ReadWrite

  • :disk_label - String. Specifies the description of the data disk.

  • :disk_size - String. Specifies the size of disk in GB

See msdn.microsoft.com/en-us/library/azure/jj157199.aspx

Returns None

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 453
def add_data_disk(vm_name, cloud_service_name, options = {})
  options[:import] ||= false
  vm = get_virtual_machine(vm_name, cloud_service_name)
  if vm
    path = "/services/hostedservices/#{cloud_service_name}/deployments/#{vm.deployment_name}/roles/#{vm_name}/DataDisks"
    body = Serialization.add_data_disk_to_xml(vm, options)
    Azure::Loggerx.info "Adding data disk to virtual machine #{vm_name} ..."
    request = client.management_request(:post, path, body: body)
    request.call
  else
    Azure::Loggerx.error "Cannot find virtual machine \"#{vm_name}\" under cloud service \"#{cloud_service_name}\"."
  end
end
add_role(params, options = {}) click to toggle source

Public: Add a new role to a cloud service. Atleast one deployment should exist before you can add a role.

Attributes

  • params - Hash. parameters.

  • options - Hash. Optional parameters.

==== Params

Accepted key/value pairs are:

  • :vm_name - String. Name of virtual machine.

  • :vm_user - String. User name for the virtual machine instance.

  • :password - String. A description for the hosted service.

  • :image - String. Name of the disk image to use to create the virtual machine.

  • :cloud_service_name - String. Name of cloud service.

==== Options

Accepted key/value pairs are:

  • :storage_account_name - String. Name of storage account.

  • :tcp_endpoints - String. Specifies the internal port and external/public port separated by a colon. You can map multiple internal and external ports by separating them with a comma.

  • :ssh_private_key_file - String. Path of private key file.

  • :ssh_port - Integer. Specifies the SSH port number.

  • +:winrm_http_port - Integer. Specifies the WinRM HTTP port number.

  • +:winrm_https_port - Integer. Specifies the WinRM HTTPS port number.

  • :vm_size - String. Specifies the size of the virtual machine instance.

  • :winrm_transport - Array. Specifies WINRM transport protocol.

Returns Azure::VirtualMachineManagement::VirtualMachine objects of newly created instance.

See: msdn.microsoft.com/en-us/library/azure/jj157186.aspx

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 173
def add_role(params, options = {})
  image = get_image(params[:image])
  options[:os_type] = image.os_type
  validate_deployment_params(params, options, true)
  cloud_services = client.cloud_service_management
  cloud_service = cloud_services.get_cloud_service_properties(params[:cloud_service_name])
  deployment_name = cloud_service.deployment_name
  Azure::Loggerx.error_with_exit "Deployment doesn't exists." if cloud_service && deployment_name.empty?
  others = {}
  if cloud_service.location
    others[:location] = cloud_service.location
  elsif cloud_service.affinity_group
    others[:affinity_group_name] = cloud_service.affinity_group
  end
  unless image.category == 'User'
    options[:storage_account_name] ||= generate_storage_account_name(params[:vm_name])
    client.storage_management.create_storage_account(options[:storage_account_name], others)
  end
  Azure::Loggerx.info 'Deployment exists, adding role...'
  existing_ports = []
  cloud_service.virtual_machines[deployment_name.to_sym].each do |vm|
    vm.tcp_endpoints.each do |endpoint|
      existing_ports << endpoint[:public_port]
    end
  end
  cloud_services.upload_certificate(options[:cloud_service_name], params[:certificate]) unless params[:certificate].empty?
  options[:existing_ports] = existing_ports
  body = Serialization.role_to_xml(params, image, options).to_xml
  path = "/services/hostedservices/#{cloud_service.name}/deployments/#{deployment_name}/roles"
  Azure::Loggerx.info 'Deployment in progress...'
  request = client.management_request(:post, path, body)
  request.call
  get_virtual_machine(params[:vm_name], cloud_service.name)
end
certificate_required?(params, options) click to toggle source
# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 524
def certificate_required?(params, options)
  if options[:os_type] == 'Linux'
    params[:password].nil?
  else
    winrm_with_https(options)
  end
end
create_virtual_machine(params, options = {}) click to toggle source

Public: Provisions a virtual machine based on the supplied configuration.

Attributes

  • params - Hash. parameters.

  • options - Hash. Optional parameters.

==== Params

Accepted key/value pairs are:

  • :vm_name - String. Name of virtual machine.

  • :vm_user - String. User name for the virtual machine instance.

  • :password - String. A description for the hosted service.

  • :image - String. Name of the disk image to use to create the virtual machine.

  • :location - String. The location where the virtual machine will be created.

  • +:affinity_group_name - String. The affinity group name to be used

for the cloud service and the storage account if these do not exist.

==== Options

Accepted key/value pairs are:

  • :storage_account_name - String. Name of storage account.

  • :cloud_service_name - String. Name of cloud service.

  • :deployment_name - String. A name for the deployment.

  • :tcp_endpoints - String. Specifies the internal port and external/public port separated by a colon. You can map multiple internal and external ports by separating them with a comma.

  • :ssh_private_key_file - String. Path of private key file.

  • :ssh_port - Integer. Specifies the SSH port number.

  • :winrm_http_port - Integer. Specifies the WinRM HTTP port number.

  • :winrm_https_port - Integer. Specifies the WinRM HTTPS port number.

  • :vm_size - String. Specifies the size of the virtual machine instance.

  • :winrm_transport - Array. Specifies WINRM transport protocol.

  • :availability_set_name - String. Specifies the availability set name.

  • :reserved_ip_name - String. Specifies the reserved IP name.

@return [Azure::VirtualMachineManagement::VirtualMachine] objects of newly created instance.

@see msdn.microsoft.com/en-us/library/azure/jj157194.aspx

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 95
def create_virtual_machine(params, options = {})
  image = get_image(params[:image])
  options[:os_type] = image.os_type
  validate_deployment_params(params, options)
  options[:deployment_name] ||= options[:cloud_service_name]
  Azure::Loggerx.info 'Creating deployment...'

  options[:cloud_service_name] ||= generate_cloud_service_name(params[:vm_name])
  options[:storage_account_name] ||= generate_storage_account_name(params[:vm_name])
  optionals = {}
  if options[:virtual_network_name]
    virtual_network_service = client.network_management
    virtual_networks = virtual_network_service.list_virtual_networks.select { |x| x.name == options[:virtual_network_name] }
    if virtual_networks.empty?
      Azure::Loggerx.error_with_exit "Virtual network #{options[:virtual_network_name]} doesn't exists"
    else
      vnet = virtual_networks.first
      if !vnet.affinity_group.empty?
        options[:affinity_group_name] = vnet.affinity_group
      else
        optionals[:location] = vnet.location
      end
    end
  elsif options[:affinity_group_name]
    optionals[:affinity_group_name] = options[:affinity_group_name]
  else
    optionals[:location] = params[:location]
  end
  cloud_service = client.cloud_service_management
  cloud_service.create_cloud_service(options[:cloud_service_name], optionals)
  cloud_service.upload_certificate(options[:cloud_service_name], params[:certificate]) unless params[:certificate].empty?
  unless image.category == 'User'
    options[:storage_account_name] ||= generate_storage_account_name(params[:vm_name])
    client.storage_management.create_storage_account(options[:storage_account_name], optionals)
  end
  body = Serialization.deployment_to_xml(params, image, options)
  path = "/services/hostedservices/#{options[:cloud_service_name]}/deployments"
  Azure::Loggerx.info 'Deployment in progress...'
  request = client.management_request(:post, path, body)
  request.call
  get_virtual_machine(params[:vm_name], options[:cloud_service_name])
rescue Exception => e
  Azure::Loggerx.error_with_exit "Failed to create virtual machine : "+e.message
end
delete_endpoint(vm_name, cloud_service_name, endpoint_name) click to toggle source

Public: Delete endpoint of virtual machine.

Attributes

  • name - String. Virtual machine name.

  • cloud_service_name - String. Cloud service name.

  • endpoint_name - String. Name of endpoint.

See msdn.microsoft.com/en-us/library/azure/jj157187.aspx

Returns NONE

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 415
def delete_endpoint(vm_name, cloud_service_name, endpoint_name)
  vm = get_virtual_machine(vm_name, cloud_service_name)
  if vm
    path = "/services/hostedservices/#{vm.cloud_service_name}/deployments/#{vm.deployment_name}/roles/#{vm_name}"
    endpoints = vm.tcp_endpoints + vm.udp_endpoints
    endpoints.delete_if { |ep| endpoint_name.downcase == ep[:name].downcase }
    body = Serialization.update_role_to_xml(endpoints, vm)
    request = client.management_request(:put, path, body: body)
    Azure::Loggerx.info "Deleting virtual machine endpoint #{endpoint_name} ..."
    request.call
  else
    Azure::Loggerx.error "Cannot find virtual machine \"#{vm_name}\" under cloud service \"#{cloud_service_name}\"."
  end
end
delete_virtual_machine(vm_name, cloud_service_name, options={}) click to toggle source

Public: Deletes the deployment, cloud service and disk.

Attributes

  • vm_name - String. Virtual machine name.

  • cloud_service_name - String. Cloud service name.

==== Options

Accepted key/value pairs are:

  • delete_vhd - Boolean. To delete the associated VHD from the blob storage location.

See msdn.microsoft.com/en-us/library/azure/gg441305.aspx See msdn.microsoft.com/en-us/library/azure/jj157179.aspx

Returns NONE

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 224
def delete_virtual_machine(vm_name, cloud_service_name, options={})
  virtual_machines = list_virtual_machines(cloud_service_name)
  vm = virtual_machines.select { |x| x.vm_name == vm_name }.first
  if vm
    if virtual_machines.size == 1
      cloud_service = client.cloud_service_management
      cloud_service.delete_cloud_service_deployment(cloud_service_name)
      cloud_service.delete_cloud_service(cloud_service_name)
    else
      path = "/services/hostedservices/#{vm.cloud_service_name}/deployments/#{vm.deployment_name}/roles/#{vm.vm_name}"
      Azure::Loggerx.info "Deleting virtual machine #{vm_name}. \n"
      request = client.management_request(:delete, path)
      request.call
    end
    Azure::Loggerx.info "Waiting for disk to be released.\n"
    disk_name = vm.disk_name
    disk_management_service = client.vm_disk_management
    # Wait for 180s for disk to be released.
    disk = nil
    18.times do
      Azure::Loggerx.info '# '
      disk = disk_management_service.get_virtual_machine_disk(disk_name)
      unless disk.attached
        Azure::Loggerx.info "Disk released.\n"
        break
      end
      sleep 10
    end
    if disk.attached
      Azure::Loggerx.error "\nCannot delete disk #{disk_name}."
    else
      disk_management_service.delete_virtual_machine_disk(disk_name, options)
    end
  else
    Azure::Loggerx.error "Cannot find virtual machine #{vm_name} under cloud service #{cloud_service_name}"
  end
rescue
end
generate_cloud_service_name(vm_name) click to toggle source
# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 479
def generate_cloud_service_name(vm_name)
  random_string(vm_name + '-service-')
end
generate_storage_account_name(vm_name) click to toggle source
# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 483
def generate_storage_account_name(vm_name)
  random_string(vm_name + 'storage').gsub(/[^0-9a-z ]/i, '').downcase[0..23]
end
get_image(image_name) click to toggle source

Private: Gets the operating system type of an image.

Returns Linux or Windows

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 472
def get_image(image_name)
  image_service = client.vm_image_management
  image = image_service.list_virtual_machine_images.select { |x| x.name.casecmp(image_name.to_s) == 0 }.first
  Azure::Loggerx.error_with_exit 'The virtual machine image source is not valid.' unless image
  image
end
get_virtual_machine(name, cloud_service_name) click to toggle source

Public: Gets a virtual machine based on the provided name and cloud service name.

Attributes

  • name - String. Virtual machine name.

  • cloud_service_name - String. Cloud service name.

Returns an Azure::VirtualMachineManagement::VirtualMachine instance.

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 51
def get_virtual_machine(name, cloud_service_name)
  server = list_virtual_machines(cloud_service_name).select { |x| x.vm_name.casecmp(name) == 0 }
  server.first
end
list_virtual_machines(*cloud_service_names) click to toggle source

Public: Get a lists of virtual machines available under the current subscription.

Returns an list of Azure::VirtualMachineManagement::VirtualMachine instances.

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 26
def list_virtual_machines(*cloud_service_names)
  roles = []
  cloud_service_names.flatten!
  if cloud_service_names.empty?
    cloud_service = client.cloud_service_management
    cloud_service_names = cloud_service.list_cloud_services.map(&:name)
  end
  cloud_service_names.each do |cloud_service_name|
    request_path = "/services/hostedservices/#{cloud_service_name}/deploymentslots/production"
    request = client.management_request(:get, request_path)
    request.warn = true
    response = request.call
    roles << Serialization.virtual_machines_from_xml(response, cloud_service_name)
  end
  roles.flatten.compact
end
restart_virtual_machine(vm_name, cloud_service_name) click to toggle source

Public: Restarts the specified virtual machine.

Attributes

  • name - String. Virtual machine name.

  • cloud_service_name - String. Cloud service name.

See msdn.microsoft.com/en-us/library/azure/jj157197.aspx

Returns NONE

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 329
def restart_virtual_machine(vm_name, cloud_service_name)
  vm = get_virtual_machine(vm_name, cloud_service_name)
  if vm
    path = "/services/hostedservices/#{vm.cloud_service_name}/deployments/#{vm.deployment_name}/roleinstances/#{vm.vm_name}/Operations"
    body = Serialization.restart_virtual_machine_to_xml
    Azure::Loggerx.info "Restarting virtual machine \"#{vm.vm_name}\" ..."
    request = client.management_request(:post, path, body: body)
    request.call
  else
    Azure::Loggerx.error "Cannot find virtual machine \"#{vm_name}\" under cloud service \"#{cloud_service_name}\"."
  end
end
shutdown_virtual_machine(vm_name, cloud_service_name) click to toggle source

Public: Shuts down the specified virtual machine.

Attributes

  • name - String. Virtual machine name.

  • cloud_service_name - String. Cloud service name.

See msdn.microsoft.com/en-us/library/azure/jj157195.aspx

Returns NONE

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 273
def shutdown_virtual_machine(vm_name, cloud_service_name)
  vm = get_virtual_machine(vm_name, cloud_service_name)
  if vm
    if %w(StoppedVM StoppedDeallocated).include?(vm.status)
      Azure::Loggerx.error 'Cannot perform the shutdown operation on a stopped virtual machine.'
    elsif vm.deployment_status == 'Running'
      path = "/services/hostedservices/#{vm.cloud_service_name}/deployments/#{vm.deployment_name}/roleinstances/#{vm.vm_name}/Operations"
      body = Serialization.shutdown_virtual_machine_to_xml
      Azure::Loggerx.info "Shutting down virtual machine \"#{vm.vm_name}\" ..."
      request = client.management_request(:post, path, body)
      request.call
    else
      Azure::Loggerx.error 'Cannot perform the shutdown operation on a stopped deployment.'
    end
  else
    Azure::Loggerx.error "Cannot find virtual machine \"#{vm_name}\" under cloud service \"#{cloud_service_name}\". "
  end
end
start_virtual_machine(vm_name, cloud_service_name) click to toggle source

Public: Starts the specified virtual machine.

Attributes

  • name - String. Virtual machine name.

  • cloud_service_name - String. Cloud service name.

See msdn.microsoft.com/en-us/library/azure/jj157189.aspx

Returns NONE

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 302
def start_virtual_machine(vm_name, cloud_service_name)
  vm = get_virtual_machine(vm_name, cloud_service_name)
  if vm
    if vm.status == 'ReadyRole'
      Azure::Loggerx.error 'Cannot perform the start operation on started virtual machine.'
    else
      path = "/services/hostedservices/#{vm.cloud_service_name}/deployments/#{vm.deployment_name}/roleinstances/#{vm.vm_name}/Operations"
      body = Serialization.start_virtual_machine_to_xml
      Azure::Loggerx.info "Starting virtual machine \"#{vm.vm_name}\" ..."
      request = client.management_request(:post, path, body: body)
      request.call
    end
  else
    Azure::Loggerx.error "Cannot find virtual machine \"#{vm_name}\" under cloud service \"#{cloud_service_name}\"."
  end
end
update_endpoints(vm_name, cloud_service_name, *input_endpoints) click to toggle source

Public: Add/Update endpoints of virtual machine.

Attributes

  • name - String. Virtual machine name.

  • cloud_service_name - String. Cloud service name.

  • input_endpoints - Hash. A hash of the name/value pairs for the endpoint.

Endpoint

Accepted key/value pairs are:

  • :local_port - String. Specifies the internal port on which the Virtual Machine is listening.

  • :public_port - String. Specifies the external port to use for the endpoint.

  • :name - String. Specifies the name of the external endpoint.

  • load_balancer_name - String. Specifies a name for a set of load-balanced endpoints.

  • :protocol - String. Specifies the transport protocol for the endpoint. Possible values are: TCP, UDP

  • :direct_server_return - String. Specifies whether the endpoint uses Direct Server Return. Possible values are: true, false (optional)

  • +:load_balancer - Hash. Contains properties that define the endpoint settings that the load balancer uses to monitor the availability of the Virtual Machine (optional)

Load balancer

Accepted key/value pairs are:

  • :port - String. Specifies the internal port on which the Virtual Machine is listening.

  • :protocol - String. Specifies the protocol to use to inspect the availability status of the virtual machine.

  • :interval - String. Specifies the interval for the load balancer probe in seconds. (optional)

  • :timeout - String. Specifies the timeout for the load balancer probe in seconds. (optional)

  • :path - String. Specifies the relative path to inspect to determine the availability status of the Virtual Machine. (optional)

See msdn.microsoft.com/en-us/library/azure/jj157187.aspx

Returns NONE

# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 385
def update_endpoints(vm_name, cloud_service_name, *input_endpoints)
  input_endpoints.flatten!
  vm = get_virtual_machine(vm_name, cloud_service_name)
  if vm
    path = "/services/hostedservices/#{vm.cloud_service_name}/deployments/#{vm.deployment_name}/roles/#{vm_name}"
    endpoints = vm.tcp_endpoints + vm.udp_endpoints
    input_endpoints.each do |iep|
      endpoints.delete_if { |ep| iep[:name].downcase == ep[:name].downcase }
    end
    endpoints += input_endpoints
    body = Serialization.update_role_to_xml(endpoints, vm)
    request = client.management_request(:put, path, body: body)
    Azure::Loggerx.info "Updating endpoints of virtual machine #{vm.vm_name} ..."
    request.call
  else
    Azure::Loggerx.error "Cannot find virtual machine \"#{vm_name}\" under cloud service \"#{cloud_service_name}\"."
  end
end
validate_deployment_params(params, options, add_role = false) click to toggle source
# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 487
def validate_deployment_params(params, options, add_role = false)
  errors = []
  params_keys = %w(vm_name image vm_user)
  params_keys += ['password'] if options[:os_type] == 'Windows'
  options_keys = []
  options_keys = %w(private_key_file) if certificate_required?(params, options)
  if add_role
    params_keys += ['cloud_service_name']
  else
    params_keys += ['location']
  end
  params_keys.each do |key|
    errors << key if params[key.to_sym].nil?
  end

  options_keys.each do |key|
    errors << key if options[key.to_sym].nil?
  end

  if errors.empty?
    validate_location(params[:location]) unless add_role
    validate_role_size(options[:vm_size])
    params[:certificate] = {}
    if certificate_required?(params, options)
      begin
        params[:certificate][:key] = OpenSSL::PKey.read File.read(options[:private_key_file])
        params[:certificate][:cert] = get_certificate(options[:private_key_file])
        params[:certificate][:fingerprint] = export_fingerprint(params[:certificate][:cert])
      rescue Exception => e
        Azure::Loggerx.error_with_exit e.message
      end
    end
  else
    Azure::Loggerx.error_with_exit "You did not provide a valid '#{errors.uniq.join(", ")}' value."
  end
end
validate_location(location_name) click to toggle source
# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 545
def validate_location(location_name)
  locations = client.base_management.list_locations
  location = locations.select { |loc| loc.name.downcase == location_name.downcase }.first
  if location.nil?
    Azure::Loggerx.error_with_exit "Value '#{location_name}' specified for parameter 'location' is invalid. Allowed values are #{locations.map(&:name).join(',')}"
  elsif !location.available_services.include?('PersistentVMRole')
    Azure::Loggerx.error_with_exit "Persistentvmrole not enabled for \"#{location.name}\". Try different location"
  end
end
validate_role_size(vm_size) click to toggle source
# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 538
def validate_role_size(vm_size)
  suggested_role_sizes = client.base_management.list_role_sizes
  if vm_size && !suggested_role_sizes.include?(vm_size)
    Azure::Loggerx.warn "Value '#{vm_size}' specified for parameter 'vm_size' is not in the list of valid VM role sizes. Suggested values are '#{suggested_role_sizes.join(',')}'"
  end
end
winrm_with_https(options) click to toggle source
# File lib/azure/virtual_machine_management/virtual_machine_management_service.rb, line 532
def winrm_with_https(options)
  if options[:os_type] == 'Windows'
    options[:winrm_transport] && options[:winrm_transport].include?('https') && options[:private_key_file]
  end
end