class Chef::Provisioning::AzureRM::Driver
Attributes
region[R]
subscription[R]
subscription_id[RW]
Public Class Methods
canonicalize_url(driver_url, config)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 40 def self.canonicalize_url(driver_url, config) scheme, account_id = driver_url.split(':', 2) if account_id.nil? || account_id.empty? subscription = Credentials.new subscription.azure_credentials_for_subscription(subscription_id) unless subscription raise "Driver #{driver_url} did not specify a subscription ID, and no default subscription was found. Have you downloaded the Azure CLI and used `azure account download` and `azure account import` to set up Azure? Alternately, you can set azure_subscriptions to [ { subscription_id: '...', management_credentials: ... }] in your Chef configuration." end config = Cheffish::MergedConfig.new({ azure_subscriptions: subscription }, config) end if subscription ["#{scheme}:#{subscription[:subscription_id]}", config] else [driver_url, config] end end
from_url(driver_url, config)
click to toggle source
Construct an AzureDriver object from a URL - used to parse existing URL data to hydrate a driver object. URL scheme: azure:subscription_id @return [AzureDriver] A chef-provisioning Azure driver object for the given URL
# File lib/chef/provisioning/azurerm/driver.rb, line 36 def self.from_url(driver_url, config) Driver.new(driver_url, config) end
new(driver_url, config)
click to toggle source
Calls superclass method
# File lib/chef/provisioning/azurerm/driver.rb, line 57 def initialize(driver_url, config) super scheme, subscription_id = driver_url.split(':', 2) self.subscription_id = subscription_id @subscription = Credentials.new.azure_credentials_for_subscription(subscription_id) unless subscription raise "Driver #{driver_url} has a subscription ID, but the system has no credentials configured for it! If you have access to this subscription, you can use `azure account download` and `azure account import` in the Azure CLI to get the credentials, or set azure_subscriptions to [ { subscription_id: '...', management_credentials: ... }] in your Chef configuration." end Chef::Config.chef_provisioning ||= {} end
Public Instance Methods
allocate_load_balancer(action_handler, lb_spec, lb_options, machine_specs)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 357 def allocate_load_balancer(action_handler, lb_spec, lb_options, machine_specs) tags = lb_options[:tags] resource_group = lb_options[:resource_group] location = lb_options[:location] virtual_network = lb_options[:virtual_network] subnet_name = lb_options[:subnet_name] subinfo = azure_net_service.subnets.get(lb_options.resource_group, lb_options.virtual_network, lb_options.subnet_name) backend_pool = [] count = backend_pool.count backend_pool[0] = Azure::ARM::Network::Models::BackendAddressPool.new backend_pool[0].name = lb_spec.name frontend_ipconf = Azure::ARM::Network::Models::FrontendIPConfiguration.new.tap do |feip| lb_options[:frontendIPConfigurations].each do |fendip| feip.name = fendip[:name] feip.subnet = subinfo feip.private_ipallocation_method = fendip[:private_ipallocation_method] end end probes = [] lb_options[:probes].each do |prbes| probe = Azure::ARM::Network::Models::Probe.new.tap do |prb| prb.name = prbes[:name] prb.port = prbes[:port] prb.protocol = prbes[:protocol] if prbes[:protocol].to_s == "http" prb.request_path = prbes[:request_path] else prb.request_path = nil end prb.interval_in_seconds = prbes[:interval_in_seconds] prb.number_of_probes = prbes[:number_of_probes] end probes.push(probe) end lb = Azure::ARM::Network::Models::LoadBalancer.new.tap do |lbinfo| lbinfo.location = location lbinfo.tags = tags lbinfo.frontend_ipconfigurations = [frontend_ipconf] lbinfo.backend_address_pools = backend_pool lbinfo.probes = probes end lb_update(resource_group, lb_spec.name, lb) # inital build mylb = azure_net_service.load_balancers.get(resource_group, lb_spec.name) machine_specs.each do |ivm| vmnic = azure_net_service.network_interfaces.get(resource_group, ivm.name) mylb.backend_address_pools.each do |pool| lb_backend_pools = vmnic.ip_configurations.first.load_balancer_backend_address_pools if lb_backend_pools lb_backend_pools.each do |backend_pool| next if backend_pool.id.eql?(pool.id) vmnic.ip_configurations.first.load_balancer_backend_address_pools.push(pool) end else vmnic.ip_configurations.first.load_balancer_backend_address_pools = [pool] end azure_net_service.network_interfaces.create_or_update(resource_group, ivm.name, vmnic) end end frontend_ipconf_sub = MsRestAzure::SubResource.new.tap do |subresource| subresource.id = azure_net_service.load_balancers.get(resource_group, lb_spec.name).frontend_ipconfigurations.first.id end backend_ipconf_sub = MsRestAzure::SubResource.new.tap do |subresource| subresource.id = mylb.backend_address_pools.first.id end unless lb_options[:inboundNatRules].nil? inboudnats = [] inat_machines = {} lb_options[:inboundNatRules].each do |ibnat| inboudnat = Azure::ARM::Network::Models::InboundNatRule.new.tap do |inat| inat_machines[ibnat[:name]] = find_vm_name(machine_specs, ibnat[:backend_ipconfiguration]) inat.name = ibnat[:name] inat.frontend_port = ibnat[:frontend_port] inat.backend_port = ibnat[:backend_port] inat.protocol = ibnat[:protocol] inat.enable_floating_ip = ibnat[:enable_floating_ip] inat.idle_timeout_in_minutes = ibnat[:idle_timeout_in_minutes] inat.frontend_ipconfiguration = frontend_ipconf_sub end inboudnats.push(inboudnat) end end lbrules = [] lb_options[:loadBalancingRules].each do |lbr| probe_sub = MsRestAzure::SubResource.new.tap do |subresource| subresource.id = find_probe_id(resource_group, lb_spec.name, lbr[:probe]) end lbrule = Azure::ARM::Network::Models::LoadBalancingRule.new.tap do |lbrs| lbrs.name = lbr[:name] lbrs.backend_address_pool = backend_ipconf_sub lbrs.protocol = lbr[:protocol] lbrs.backend_port = lbr[:backend_port] lbrs.frontend_port = lbr[:frontend_port] lbrs.idle_timeout_in_minutes = lbr[:idle_timeout_in_minutes] lbrs.enable_floating_ip = lbr[:enable_floating_ip] lbrs.load_distribution = lbr[:load_distribution] lbrs.frontend_ipconfiguration = frontend_ipconf_sub lbrs.backend_address_pool = backend_ipconf_sub lbrs.probe = probe_sub end lbrules.push(lbrule) end lb = Azure::ARM::Network::Models::LoadBalancer.new.tap do |lbinfo| lbinfo.location = location lbinfo.tags = tags lbinfo.frontend_ipconfigurations = [frontend_ipconf] lbinfo.backend_address_pools = backend_pool unless lb_options[:inboundNatRules].nil? lbinfo.inbound_nat_rules = inboudnats end lbinfo.probes = probes lbinfo.load_balancing_rules = lbrules end lb_update(resource_group, lb_spec.name, lb) # update additions build mylb = azure_net_service.load_balancers.get(resource_group, lb_spec.name) if lb_options[:inboundNatRules] mylb.inbound_nat_rules.each do |inat| vm_name = inat_machines[inat.name] vmnic = azure_net_service.network_interfaces.get(resource_group, vm_name) lb_inbound_nat_rules = vmnic.ip_configurations.first.load_balancer_inbound_nat_rules if lb_inbound_nat_rules lb_inbound_nat_rules.each do |inat_rule| next if inat_rule.id.eql?(inat.id) vmnic.ip_configurations.first.load_balancer_inbound_nat_rules.push(inat) end else vmnic.ip_configurations.first.load_balancer_inbound_nat_rules = [inat] end azure_net_service.network_interfaces.create_or_update(resource_group, vm_name, vmnic) end end lb_spec.reference = { 'frontend_ipconfigurations' => mylb.frontend_ipconfigurations.first.private_ipaddress, 'allocated_at' => Time.now.utc.to_s, } end
allocate_machine(action_handler, machine_spec, machine_options)
click to toggle source
Allocate a new machine with the Azure API and start it up, without blocking to wait for it. Creates any needed resources to get a machine up and running. @param (see Chef::Provisioning::Driver#allocate_machine)
# File lib/chef/provisioning/azurerm/driver.rb, line 87 def allocate_machine(action_handler, machine_spec, machine_options) existing_vm = vm_for(machine_spec) # We don't need to do anything if the existing VM is found return if existing_vm bootstrap_options = (machine_options[:bootstrap_options] || {}).dup vm_name = machine_spec.name location = bootstrap_options[:location] || machine_options[:location] resource_group_name = bootstrap_options[:resource_group_name] availability_set = bootstrap_options[:availability_set] osProfile = bootstrap_options[:osProfile] network_security_group_name = bootstrap_options[:network_security_group_name] tags = bootstrap_options[:tags] raise 'location not provided, where the virtual machine should be created' unless location raise 'resource_group_name not provided, where the virtual machine should be created' unless resource_group_name raise 'osProfile properties not provided in bootstrap_options' unless osProfile computerName = osProfile[:computerName] adminPassword = osProfile[:adminPassword] adminUsername = osProfile[:adminUsername] linuxConfiguration = osProfile[:linuxConfiguration] raise 'adminUsername under osProfile properties not provided in bootstrap_options' unless adminUsername Chef::Log.debug "Azure machine_options: #{machine_options.inspect}" action_handler.report_progress "Creating #{machine_spec.name} in #{location} with supplied parameters..." if availability_set action_handler.report_progress "Looking for availability_set #{availability_set}." begin availability_set_id = azure_vm_service.availability_sets.get(resource_group_name, availability_set).id rescue MsRestAzure::AzureOperationError => e if e.error_code.eql?('ResourceNotFound') action_handler.report_progress "availability_set #{availability_set} not found, Creating it..." sku = Azure::ARM::Compute::Models::Sku.new.tap do |sku| sku.name = 'Aligned' end aSet = Azure::ARM::Compute::Models::AvailabilitySet.new.tap do |set| set.platform_fault_domain_count = 3 set.platform_update_domain_count = 3 set.location = location set.sku = sku end res = azure_vm_service.availability_sets.create_or_update(resource_group_name, availability_set, aSet) availability_set_id = res.id else raise e end end raise "availability_set #{availability_set} under resource group #{resource_group_name} was not found." unless availability_set_id availabilitySet = MsRestAzure::SubResource.new.tap do |subResource| subResource.id = availability_set_id end end action_handler.report_progress "Preparing OS disk for the VM #{vm_name}..." begin os_disk_exist = azure_vm_service.disks.get(resource_group_name, "#{vm_name}_os_disk") rescue MsRestAzure::AzureOperationError os_disk_exist = nil end if os_disk_exist action_handler.report_progress "OS disk with the name #{vm_name}_os_disk already exist." action_handler.report_progress 'checking attached status...' if os_disk_exist.managed_by.nil? action_handler.report_progress "OS disk #{vm_name} not attached to any VM. Using this..." os_disk = Azure::ARM::Compute::Models::OSDisk.new.tap do |os_disk| os_disk.create_option = 'attach' os_disk.os_type = machine_spec.reference['is_windows'] ? 'Windows' : 'Linux' os_disk.managed_disk = Azure::ARM::Compute::Models::ManagedDiskParameters.new.tap do |managedDisk| managedDisk.id = os_disk_exist.id end end else raise "OS disk #{vm_name} attached to a VM. Contact your cloud administrator or change VM name." end else os_disk = Azure::ARM::Compute::Models::OSDisk.new.tap do |os_disk| os_disk.name = "#{vm_name}_os_disk" os_disk.create_option = Azure::ARM::Compute::Models::DiskCreateOptionTypes::FromImage os_disk.managed_disk = Azure::ARM::Compute::Models::ManagedDiskParameters.new.tap do |managedDisk| managedDisk.storage_account_type = bootstrap_options[:storageProfile][:storage_account_type] end end end begin subnet = azure_net_service.subnets.get(resource_group_name, bootstrap_options[:virtual_network_name], bootstrap_options[:subnet_name]) rescue MsRestAzure::AzureOperationError => e raise e.message end action_handler.report_progress "Creating a network interface for the VM #{vm_name}" begin nic_exist = azure_net_service.network_interfaces.get(resource_group_name, vm_name) rescue MsRestAzure::AzureOperationError nic_exist = nil end if nic_exist action_handler.report_progress "network interface with the name #{vm_name} already exist." action_handler.report_progress 'checking attached status...' if nic_exist.virtual_machine.nil? action_handler.report_progress "network interface #{vm_name} not attached to any VM. Using this..." nic = nic_exist else raise "network interface #{vm_name} attached to a VM. Contact your cloud administrator or change VM name." end else begin network_security_group = azure_net_service.network_security_groups.get(resource_group_name, network_security_group_name) if network_security_group_name rescue MsRestAzure::AzureOperationError => e raise e.message end nic = azure_net_service.network_interfaces.create_or_update( resource_group_name, vm_name, Azure::ARM::Network::Models::NetworkInterface.new.tap do |interface| interface.location = location interface.network_security_group = network_security_group if network_security_group_name interface.ip_configurations = [ Azure::ARM::Network::Models::NetworkInterfaceIPConfiguration.new.tap do |nic_conf| nic_conf.name = vm_name nic_conf.private_ipallocation_method = Azure::ARM::Network::Models::IPAllocationMethod::Dynamic nic_conf.subnet = subnet end ] end ) end vm_create_params = Azure::ARM::Compute::Models::VirtualMachine.new.tap do |vm| vm.location = location vm.availability_set = availabilitySet if availability_set && availability_set_id vm.tags = tags if tags unless os_disk_exist vm.os_profile = Azure::ARM::Compute::Models::OSProfile.new.tap do |os_profile| os_profile.computer_name = computerName if computerName os_profile.admin_username = adminUsername os_profile.admin_password = adminPassword if adminPassword if linuxConfiguration os_profile.linux_configuration = Azure::ARM::Compute::Models::LinuxConfiguration.new.tap do |linux| linux.disable_password_authentication = linuxConfiguration[:disablePasswordAuthentication].nil? ? true : linuxConfiguration[:disablePasswordAuthentication] if ssh = linuxConfiguration[:ssh] linux.ssh = Azure::ARM::Compute::Models::SshConfiguration.new.tap do |ssh_config| if publicKeys = ssh[:publicKeys] public_keys = [] publicKeys.each do |publicKey| sshPublicKey = Azure::ARM::Compute::Models::SshPublicKey.new.tap do |pub_key| pub_key.path = publicKey[:path] || "/home/#{adminUsername}/.ssh/authorized_keys" if publicKey[:keyData] pub_key.key_data = publicKey[:keyData] else raise 'public key keyData not provided' end end public_keys << sshPublicKey end ssh_config.public_keys = public_keys end end end end end end end vm.storage_profile = Azure::ARM::Compute::Models::StorageProfile.new.tap do |store_profile| unless os_disk_exist store_profile.image_reference = Azure::ARM::Compute::Models::ImageReference.new.tap do |ref| ref.publisher = bootstrap_options[:storageProfile][:imageReference][:publisher] ref.offer = bootstrap_options[:storageProfile][:imageReference][:offer] ref.sku = bootstrap_options[:storageProfile][:imageReference][:sku] ref.version = bootstrap_options[:storageProfile][:imageReference][:version] end end store_profile.os_disk = os_disk end vm.hardware_profile = Azure::ARM::Compute::Models::HardwareProfile.new.tap do |hardware| hardware.vm_size = bootstrap_options[:hardwareProfile][:vmSize] end vm.network_profile = Azure::ARM::Compute::Models::NetworkProfile.new.tap do |net_profile| net_profile.network_interfaces = [ Azure::ARM::Compute::Models::NetworkInterfaceReference.new.tap do |ref| ref.id = nic.id ref.primary = true end ] end end vm = azure_vm_service.virtual_machines.create_or_update(resource_group_name, machine_spec.name, vm_create_params) machine_spec.reference = { 'driver_version' => Chef::Provisioning::AzureRM::VERSION, 'allocated_at' => Time.now.utc.to_s, 'host_node' => action_handler.host_node, 'location' => location, 'resource_group_name' => resource_group_name, 'adminUsername' => adminUsername } machine_spec.driver_url = driver_url machine_spec.reference['key_name'] = bootstrap_options[:key_name] if bootstrap_options[:key_name] machine_spec.reference['transport_address_location'] = machine_options[:transport_address_location] if machine_options[:transport_address_location] machine_spec.reference['vm_name'] = machine_spec.name machine_spec.reference['is_windows'] = case vm.storage_profile.os_disk.os_type.downcase when 'windows' true else false end action_handler.report_progress "Created #{machine_spec.name} in #{location}..." end
connect_to_machine(name, chef_server = nil)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 300 def connect_to_machine(name, chef_server = nil) machine_spec = if name.is_a?(MachineSpec) name else Chef::Provisioning::ChefMachineSpec.get(name, chef_server) end machine_for(machine_spec, machine_spec.reference) end
deep_symbolize_keys(hash_like)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 71 def deep_symbolize_keys(hash_like) return {} if hash_like.nil? || hash_like.empty? r = {} hash_like.each do |key, value| value = deep_symbolize_keys(value) if value.respond_to?(:values) r[key.to_sym] = value end r end
destroy_load_balancer(action_handler, lb_spec, lb_options)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 526 def destroy_load_balancer(action_handler, lb_spec, lb_options) raise "#{lb_spec.name} hasn't recived a resource group. Unable to destroy." unless lb_options.resource_group azure_net_service.load_balancers.delete(lb_options.resource_group, lb_spec.name) # Remove LB spec from databag lb_spec.delete(action_handler) end
destroy_machine(action_handler, machine_spec, _machine_options)
click to toggle source
(see Chef::Provisioning::Driver#destroy_machine)
# File lib/chef/provisioning/azurerm/driver.rb, line 337 def destroy_machine(action_handler, machine_spec, _machine_options) vm = vm_for(machine_spec) vm_name = machine_spec.name resource_group_name = machine_spec.reference['resource_group_name'] # Check if we need to proceed return if vm.nil? || vm_name.nil? || resource_group_name.nil? # Skip if we don't actually need to do anything return unless action_handler.should_perform_actions # TODO: action_handler.do |block| ? action_handler.report_progress "Destroying VM #{machine_spec.name}" azure_vm_service.virtual_machines.delete(resource_group_name, vm_name) action_handler.report_progress "Destroying OS disk for machine #{vm_name}" azure_vm_service.disks.delete(resource_group_name, "#{vm_name}_os_disk") action_handler.report_progress "Destroying network interface #{machine_spec.name}" azure_net_service.network_interfaces.delete(resource_group_name, vm_name) action_handler.report_progress "Destroyed VM #{machine_spec.name}" end
find_probe_id(resource_group, lb_name, probe_name)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 515 def find_probe_id(resource_group, lb_name, probe_name) probes = azure_net_service.load_balancers.get(resource_group, lb_name).probes probes.each do |probe| return probe.id if probe.name.eql?(probe_name) end end
find_vm_name(machine_specs, vm_name)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 509 def find_vm_name(machine_specs, vm_name) machine_specs.each do |vm| return vm.name if vm.name.include?(vm_name) end end
lb_update(resource_group, name, lb)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 522 def lb_update(resource_group, name, lb) azure_net_service.load_balancers.create_or_update(resource_group, name, lb) end
ready_machine(action_handler, machine_spec, machine_options)
click to toggle source
(see Chef::Provisioning::Driver#ready_machine)
# File lib/chef/provisioning/azurerm/driver.rb, line 311 def ready_machine(action_handler, machine_spec, machine_options) machine_options = deep_symbolize_keys(machine_options) vm = vm_for(machine_spec) if vm.nil? raise "Machine #{machine_spec.name} does not have a VM associated with it, or the VM does not exist." end case machine_power_state(vm) when 'running' action_handler.report_progress "#{machine_spec.name} is ready" when 'stopped' action_handler.report_progress "#{machine_spec.name} is stopped. Driver can't start it, please contact admin" raise "#{machine_spec.name} is stopped" # TODO: start the VM when nil raise "Could not find power state of #{machine_spec.name}" else action_handler.report_progress "Waiting for #{machine_spec.name} to become ready..." wait_until_ready(action_handler, machine_spec) end wait_for_transport(action_handler, machine_spec, machine_options) machine_for(machine_spec, machine_options, vm) end
Private Instance Methods
azure_net_service()
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 557 def azure_net_service credentials = Credentials.new.azure_credentials_for_subscription(subscription_id) client = Azure::ARM::Network::NetworkManagementClient.new(credentials) client.subscription_id = subscription_id client end
azure_vm_service()
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 550 def azure_vm_service credentials = Credentials.new.azure_credentials_for_subscription(subscription_id) client = Azure::ARM::Compute::ComputeManagementClient.new(credentials) client.subscription_id = subscription_id client end
convergence_strategy_for(machine_spec, machine_options)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 679 def convergence_strategy_for(machine_spec, machine_options) # Tell Ohai that this is an Azure VM so that it runs the azure plugin convergence_options = Cheffish::MergedConfig.new( machine_options[:convergence_options] || {}, ohai_hints: { 'azure' => '' } ) # Defaults unless machine_spec.reference return Chef::Provisioning::ConvergenceStrategy::NoConverge.new(convergence_options, config) end if machine_spec.reference['is_windows'] raise 'Sorry, No windows convergance support yet.' elsif machine_options[:cached_installer] == true Chef::Provisioning::ConvergenceStrategy::InstallCached.new(convergence_options, config) else Chef::Provisioning::ConvergenceStrategy::InstallSh.new(convergence_options, config) end end
create_ssh_transport(machine_spec, machine_options, vm)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 591 def create_ssh_transport(machine_spec, machine_options, vm) ssh_options = ssh_options_for(machine_spec, machine_options, vm) username = machine_spec.reference['adminUsername'] || default_ssh_username options = {} if machine_spec.reference[:sudo] || (!machine_spec.reference.key?(:sudo) && username != 'root') options[:prefix] = 'sudo ' end # Enable pty by default options[:ssh_pty_enable] = true if machine_spec.reference.key?('ssh_gateway') options[:ssh_gateway] = machine_spec.reference['ssh_gateway'] elsif machine_options[:ssh_gateway] options[:ssh_gateway] = machine_options[:ssh_gateway] end remote_host = determine_remote_host(machine_spec, vm) Chef::Provisioning::Transport::SSH.new(remote_host, username, ssh_options, options, config) end
default_ssh_username()
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 564 def default_ssh_username 'ubuntu' end
determine_remote_host(machine_spec, vm)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 610 def determine_remote_host(machine_spec, vm) transport_address_location = (machine_spec.reference['transport_address_location'] || :private_ip).to_sym Chef::Log.warn("This driver only supports private ip address. Using private ip. Set machine_options ':transport_address_location => :private_ip' ...") if transport_address_location != :private_ip private_ip_address_for(vm) end
get_primary_network_interface(network_interfaces)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 650 def get_primary_network_interface(network_interfaces) network_interfaces.each do |network_interface| return network_interface if network_interface.primary end end
get_primary_private_ip_address(ip_configurations)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 656 def get_primary_private_ip_address(ip_configurations) ip_configurations.each do |ip_configuration| return ip_configuration['properties']['privateIPAddress'] if ip_configuration['properties']['primary'] end end
machine_for(machine_spec, machine_options, vm = nil)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 536 def machine_for(machine_spec, machine_options, vm = nil) vm ||= vm_for(machine_spec) raise "VM for node #{machine_spec.name} has not been created!" unless vm transport = transport_for(machine_spec, machine_options, vm) convergence_strategy = convergence_strategy_for(machine_spec, machine_options) if machine_spec.reference['is_windows'] raise 'Sorry, No windows convergance support yet.' else Chef::Provisioning::Machine::UnixMachine.new(machine_spec, transport, convergence_strategy) end end
machine_power_state(vm)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 746 def machine_power_state(vm) statuses = vm.instance_view.statuses statuses.each do |status| return status.code.split('/').last if status.code.split('/').first.eql?('PowerState') end nil end
machine_provisioning_state(vm)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 754 def machine_provisioning_state(vm) statuses = vm.instance_view.statuses statuses.each do |status| return status.code.split('/').last if status.code.split('/').first.eql?('ProvisioningState') end nil end
private_ip_address_for(vm)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 628 def private_ip_address_for(vm) network_profile = vm.network_profile network_interfaces = network_profile.network_interfaces primary_network_interface = get_primary_network_interface(network_interfaces) api_version = '2017-03-01' request_headers = {} # Set Headers request_headers['x-ms-client-request-id'] = SecureRandom.uuid request_headers['accept-language'] = azure_net_service.accept_language unless azure_net_service.accept_language.nil? request_url = azure_net_service.base_url options = { middlewares: [[MsRest::RetryPolicyMiddleware, times: 3, retry: 0.02], [:cookie_jar]], query_params: { 'api-version' => api_version, '$expand' => nil }, headers: request_headers, base_url: request_url } ip_configurations = azure_net_service.make_request(:get, primary_network_interface.id, options)['properties']['ipConfigurations'] get_primary_private_ip_address(ip_configurations) end
private_key_for(machine_spec, machine_options, _vm)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 662 def private_key_for(machine_spec, machine_options, _vm) if machine_spec.reference['key_name'] key = get_private_key(machine_spec.reference['key_name']) unless key raise "Server was created with key name '#{machine_spec.reference['key_name']}', but the corresponding private key was not found locally. Check if the key is in Chef::Config.private_key_paths: #{Chef::Config.private_key_paths.join(', ')}" end key elsif machine_options[:bootstrap_options] && machine_options[:bootstrap_options][:key_path] IO.read(machine_options[:bootstrap_options][:key_path]) elsif machine_options[:bootstrap_options] && machine_options[:bootstrap_options][:key_name] get_private_key(machine_options[:bootstrap_options][:key_name]) else # TODO: make a way to suggest other keys to try ... raise "No key found to connect to #{machine_spec.name} (#{machine_spec.reference.inspect})!" end end
ssh_options_for(machine_spec, machine_options, vm)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 616 def ssh_options_for(machine_spec, machine_options, vm) result = { auth_methods: ['publickey'], keys_only: true }.merge(machine_options[:ssh_options] || {}) unless result.key?(:key_data) result[:keys_only] = true result[:key_data] = [private_key_for(machine_spec, machine_options, vm)] end result end
transport_for(machine_spec, machine_options, vm)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 583 def transport_for(machine_spec, machine_options, vm) if machine_spec.reference['is_windows'] raise 'Sorry, No windows convergance support yet.' else create_ssh_transport(machine_spec, machine_options, vm) end end
vm_for(machine_spec)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 568 def vm_for(machine_spec) if machine_spec.reference if machine_spec.driver_url != driver_url raise "Switching a machine's driver from #{machine_spec.driver_url} to #{driver_url} is not currently supported! Use machine :destroy and then re-create the machine on the new driver." elsif machine_spec.reference['resource_group_name'].nil? || machine_spec.name.nil? return nil end begin return azure_vm_service.virtual_machines.get(machine_spec.reference['resource_group_name'], machine_spec.name, 'instanceView') rescue MsRestAzure::AzureOperationError return nil end end end
wait_for_transport(action_handler, machine_spec, machine_options)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 724 def wait_for_transport(action_handler, machine_spec, machine_options) vm = vm_for(machine_spec) sleep_time = 10 transport = transport_for(machine_spec, machine_options, vm) unless transport.available? if action_handler.should_perform_actions action_handler.report_progress "waiting for #{machine_spec.name} (#{driver_url}) to be connectable (transport up and running) ..." max_wait_time = Chef::Config.chef_provisioning[:machine_max_wait_time] || 120 Retryable.retryable( tries: (max_wait_time / sleep_time).to_i, sleep: sleep_time, matching: /did not become connectable within/ ) do |retries, _exception| action_handler.report_progress "been waiting #{sleep_time * retries}/#{max_wait_time} -- sleeping #{sleep_time} seconds for #{machine_spec.name} (#{driver_url}) to become connectable ..." unless transport.available? raise "VM #{machine_spec.name} (#{driver_url}) did not become connectable within #{max_wait_time} seconds" end end end end end
wait_until_ready(action_handler, machine_spec)
click to toggle source
# File lib/chef/provisioning/azurerm/driver.rb, line 700 def wait_until_ready(action_handler, machine_spec) vm = vm_for(machine_spec) # If the machine is ready, nothing to do return if machine_power_state(vm) == 'running' # Skip if we don't actually need to do anything return unless action_handler.should_perform_actions time_elapsed = 0 sleep_time = 10 max_wait_time = 120 action_handler.report_progress "waiting for #{machine_spec.name} to be ready ..." while time_elapsed < 120 && machine_power_state(vm) == 'running' action_handler.report_progress "#{time_elapsed}/#{max_wait_time}s..." sleep(sleep_time) time_elapsed += sleep_time # Azure caches results vm = vm_for(machine_spec) end action_handler.report_progress "#{machine_spec.name} is now ready" end