class Bosh::Director::VmCreator
Creates VM model and call out to CPI to create VM in IaaS
Public Class Methods
new(cloud, logger, vm_deleter, disk_manager, job_renderer, arp_flusher)
click to toggle source
# File lib/bosh/director/vm_creator.rb, line 10 def initialize(cloud, logger, vm_deleter, disk_manager, job_renderer, arp_flusher) @cloud = cloud @logger = logger @vm_deleter = vm_deleter @disk_manager = disk_manager @job_renderer = job_renderer @arp_flusher = arp_flusher end
Private Class Methods
generate_agent_id()
click to toggle source
# File lib/bosh/director/vm_creator.rb, line 181 def self.generate_agent_id SecureRandom.uuid end
Public Instance Methods
create_for_instance_plan(instance_plan, disks)
click to toggle source
# File lib/bosh/director/vm_creator.rb, line 49 def create_for_instance_plan(instance_plan, disks) instance = instance_plan.instance instance_model = instance.model @logger.info('Creating VM') create( instance_model, instance.stemcell, instance.cloud_properties, instance_plan.network_settings_hash, disks, instance.env, ) begin VmMetadataUpdater.build.update(instance_model, {}) agent_client = AgentClient.with_vm_credentials_and_agent_id(instance_model.credentials, instance_model.agent_id) agent_client.wait_until_ready if Config.flush_arp ip_addresses = instance_plan.network_settings_hash.map do |index,network| network['ip'] end.compact @arp_flusher.delete_arp_entries(instance_model.vm_cid, ip_addresses) end instance.update_trusted_certs instance.update_cloud_properties! rescue Exception => e @logger.error("Failed to create/contact VM #{instance_model.vm_cid}: #{e.inspect}") if Config.keep_unreachable_vms @logger.info('Keeping the VM for debugging') else @vm_deleter.delete_for_instance(instance_model) end raise e end @disk_manager.attach_disks_if_needed(instance_plan) apply_initial_vm_state(instance_plan) instance_plan.mark_desired_network_plans_as_existing end
create_for_instance_plans(instance_plans, ip_provider)
click to toggle source
# File lib/bosh/director/vm_creator.rb, line 19 def create_for_instance_plans(instance_plans, ip_provider) return @logger.info('No missing vms to create') if instance_plans.empty? total = instance_plans.size event_log_stage = Config.event_log.begin_stage('Creating missing vms', total) ThreadPool.new(max_threads: Config.max_threads, logger: @logger).wrap do |pool| instance_plans.each do |instance_plan| instance = instance_plan.instance pool.process do with_thread_name("create_missing_vm(#{instance.model}/#{total})") do event_log_stage.advance_and_track(instance.model.to_s) do @logger.info('Creating missing VM') disks = [instance.model.persistent_disk_cid].compact create_for_instance_plan(instance_plan, disks) instance_plan.network_plans .select(&:obsolete?) .each do |network_plan| reservation = network_plan.reservation ip_provider.release(reservation) end instance_plan.release_obsolete_network_plans end end end end end end
Private Instance Methods
add_event(deployment_name, instance_name, action, object_name = nil, parent_id = nil, error = nil)
click to toggle source
# File lib/bosh/director/vm_creator.rb, line 97 def add_event(deployment_name, instance_name, action, object_name = nil, parent_id = nil, error = nil) event = Config.current_job.event_manager.create_event( { parent_id: parent_id, user: Config.current_job.username, action: action, object_type: 'vm', object_name: object_name, task: Config.current_job.task_id, deployment: deployment_name, instance: instance_name, error: error }) event.id end
apply_initial_vm_state(instance_plan)
click to toggle source
# File lib/bosh/director/vm_creator.rb, line 113 def apply_initial_vm_state(instance_plan) instance_plan.instance.apply_initial_vm_state(instance_plan.spec) unless instance_plan.instance.compilation? # re-render job templates with updated dynamic network settings @logger.debug("Re-rendering templates with spec: #{instance_plan.spec.as_template_spec}") @job_renderer.render_job_instance(instance_plan) end end
create(instance_model, stemcell, cloud_properties, network_settings, disks, env)
click to toggle source
# File lib/bosh/director/vm_creator.rb, line 123 def create(instance_model, stemcell, cloud_properties, network_settings, disks, env) parent_id = add_event(instance_model.deployment.name, instance_model.name, 'create') agent_id = self.class.generate_agent_id env = Bosh::Common::DeepCopy.copy(env) options = {:agent_id => agent_id} if Config.encryption? credentials = generate_agent_credentials env['bosh'] ||= {} env['bosh']['credentials'] = credentials options[:credentials] = credentials end password = env.fetch('bosh', {}).fetch('password', "") if Config.generate_vm_passwords && password == "" env['bosh'] ||= {} env['bosh']['password'] = sha512_hashed_password end if instance_model.job env['bosh'] ||= {} env['bosh']['group'] = Canonicalizer.canonicalize("#{Bosh::Director::Config.name}-#{instance_model.deployment.name}-#{instance_model.job}") env['bosh']['groups'] = [ Bosh::Director::Config.name, instance_model.deployment.name, instance_model.job, "#{Bosh::Director::Config.name}-#{instance_model.deployment.name}", "#{instance_model.deployment.name}-#{instance_model.job}", "#{Bosh::Director::Config.name}-#{instance_model.deployment.name}-#{instance_model.job}" ] env['bosh']['groups'].map! { |name| Canonicalizer.canonicalize(name) } end count = 0 begin vm_cid = @cloud.create_vm(agent_id, stemcell.cid, cloud_properties, network_settings, disks, env) rescue Bosh::Clouds::VMCreationFailed => e count += 1 @logger.error("failed to create VM, retrying (#{count})") retry if e.ok_to_retry && count < Config.max_vm_create_tries raise e end options[:vm_cid] = vm_cid instance_model.update(options) rescue => e @logger.error("error creating vm: #{e.message}") if vm_cid parent_id = add_event(instance_model.deployment.name, instance_model.name, 'delete', vm_cid) @vm_deleter.delete_vm(vm_cid) add_event(instance_model.deployment.name, instance_model.name, 'delete', vm_cid, parent_id) end raise e ensure add_event(instance_model.deployment.name, instance_model.name, 'create', vm_cid, parent_id, e) end