class VagrantPlugins::Openstack::Action::CreateServer

Public Class Methods

new(app, _env, resolver = ConfigResolver.new, utils = Utils.new) click to toggle source
# File lib/vagrant-openstack-provider/action/create_server.rb, line 17
def initialize(app, _env, resolver = ConfigResolver.new, utils = Utils.new)
  @app = app
  @logger = Log4r::Logger.new('vagrant_openstack::action::create_server')
  @resolver = resolver
  @utils = utils
  @@mutex = Mutex.new
end

Public Instance Methods

execute(env) click to toggle source
# File lib/vagrant-openstack-provider/action/create_server.rb, line 25
def execute(env)
  @logger.info 'Start create server action'

  config = env[:machine].provider_config

  fail Errors::MissingBootOption if config.image.nil? && config.volume_boot.nil?
  fail Errors::ConflictBootOption unless config.image.nil? || config.volume_boot.nil?

  options = {
    flavor: @resolver.resolve_flavor(env),
    image: @resolver.resolve_image(env),
    volume_boot: @resolver.resolve_volume_boot(env),
    networks: @resolver.resolve_networks(env),
    volumes: @resolver.resolve_volumes(env),
    keypair_name: @resolver.resolve_keypair(env),
    availability_zone: env[:machine].provider_config.availability_zone,
    scheduler_hints: env[:machine].provider_config.scheduler_hints,
    security_groups: @resolver.resolve_security_groups(env),
    user_data: env[:machine].provider_config.user_data,
    metadata: env[:machine].provider_config.metadata
  }

  server_id = create_server(env, options)

  # Store the ID right away so we can track it
  env[:machine].id = server_id

  waiting_for_server_to_be_built(env, server_id)
  @@mutex.synchronize do
    assign_floating_ip(env, server_id)
    waiting_for_floating_ip_to_be_assigned(env, server_id)
  end
  attach_volumes(env, server_id, options[:volumes]) unless options[:volumes].empty?

  @app.call(env)
end

Private Instance Methods

assign_floating_ip(env, server_id) click to toggle source
# File lib/vagrant-openstack-provider/action/create_server.rb, line 151
def assign_floating_ip(env, server_id)
  floating_ip = @resolver.resolve_floating_ip(env)
  return if !floating_ip || floating_ip.empty?
  @logger.info "Using floating IP #{floating_ip}"
  env[:ui].info(I18n.t('vagrant_openstack.using_floating_ip', floating_ip: floating_ip))
  env[:openstack_client].nova.add_floating_ip(env, server_id, floating_ip)
rescue Errors::UnableToResolveFloatingIP
  @logger.info 'Vagrant was unable to resolve FloatingIP, continue assuming it is not necessary'
end
attach_volumes(env, server_id, volumes) click to toggle source
# File lib/vagrant-openstack-provider/action/create_server.rb, line 177
def attach_volumes(env, server_id, volumes)
  @logger.info("Attaching volumes #{volumes} to server #{server_id}")
  volumes.each do |volume|
    @logger.debug("Attaching volumes #{volume}")
    env[:openstack_client].nova.attach_volume(env, server_id, volume[:id], volume[:device])
  end
end
create_server(env, options) click to toggle source
# File lib/vagrant-openstack-provider/action/create_server.rb, line 64
def create_server(env, options)
  config = env[:machine].provider_config
  nova = env[:openstack_client].nova
  server_name = config.server_name || env[:machine].name

  env[:ui].info(I18n.t('vagrant_openstack.launching_server'))
  env[:ui].info(" -- Tenant          : #{config.tenant_name}")
  env[:ui].info(" -- Name            : #{server_name}")
  env[:ui].info(" -- Flavor          : #{options[:flavor].name}")
  env[:ui].info(" -- FlavorRef       : #{options[:flavor].id}")
  unless options[:image].nil?
    env[:ui].info(" -- Image           : #{options[:image].name}")
    env[:ui].info(" -- ImageRef        : #{options[:image].id}")
  end
  env[:ui].info(" -- Boot volume     : #{options[:volume_boot][:id]} (#{options[:volume_boot][:device]})") unless options[:volume_boot].nil?
  env[:ui].info(" -- KeyPair         : #{options[:keypair_name]}") unless options[:keypair_name].nil?

  unless options[:networks].empty?
    formated_networks = ' -- '
    if options[:networks].size == 1
      formated_networks << 'Network         : '
    else
      formated_networks << 'Networks        : '
    end
    formated_networks << options[:networks].map do |n|
      if n.key? :fixed_ip
        "#{n[:uuid]} (#{n[:fixed_ip]})"
      else
        n[:uuid]
      end
    end.join(', ')
    env[:ui].info(formated_networks)
  end

  unless options[:volumes].empty?
    options[:volumes].each do |volume|
      device = volume[:device]
      device = :auto if device.nil?
      env[:ui].info(" -- Volume attached : #{volume[:id]} => #{device}")
    end
  end

  log = "Launching server '#{server_name}' in project '#{config.tenant_name}' "
  log << "with flavor '#{options[:flavor].name}' (#{options[:flavor].id}), "
  unless options[:image].nil?
    log << "image '#{options[:image].name}' (#{options[:image].id}) "
  end
  unless options[:keypair_name].nil?
    log << "and keypair '#{options[:keypair_name]}'"
  end

  @logger.info(log)

  image_ref = options[:image].id unless options[:image].nil?

  create_opts = {
    name: server_name,
    image_ref: image_ref,
    volume_boot: options[:volume_boot],
    flavor_ref: options[:flavor].id,
    keypair: options[:keypair_name],
    availability_zone: options[:availability_zone],
    networks: options[:networks],
    scheduler_hints: options[:scheduler_hints],
    security_groups: options[:security_groups],
    user_data: options[:user_data],
    metadata: options[:metadata]
  }

  nova.create_server(env, create_opts)
end
waiting_for_floating_ip_to_be_assigned(env, server_id, retry_interval = 3) click to toggle source
# File lib/vagrant-openstack-provider/action/create_server.rb, line 161
def waiting_for_floating_ip_to_be_assigned(env, server_id, retry_interval = 3)
  floating_ip = @resolver.resolve_floating_ip(env)
  return if !floating_ip || floating_ip.empty?
  @logger.info "Waiting for floating IP #{floating_ip} to be assigned"
  env[:ui].info(I18n.t('vagrant_openstack.waiting_for_floating_ip', floating_ip: floating_ip))
  config = env[:machine].provider_config
  Timeout.timeout(config.floating_ip_assign_timeout, Errors::Timeout) do
    until env[:openstack_client].nova.check_assigned_floating_ip(env, server_id, floating_ip)
      sleep retry_interval
    end
    return
  end
rescue Errors::UnableToResolveFloatingIP
  @logger.info 'Vagrant was unable to resolve FloatingIP, not waiting for assignment'
end
waiting_for_server_to_be_built(env, server_id, retry_interval = 3) click to toggle source
# File lib/vagrant-openstack-provider/action/create_server.rb, line 136
def waiting_for_server_to_be_built(env, server_id, retry_interval = 3)
  @logger.info "Waiting for the server with id #{server_id} to be built..."
  env[:ui].info(I18n.t('vagrant_openstack.waiting_for_build'))
  config = env[:machine].provider_config
  Timeout.timeout(config.server_create_timeout, Errors::Timeout) do
    server_status = 'WAITING'
    until server_status == 'ACTIVE'
      @logger.debug('Waiting for server to be ACTIVE')
      server_status = env[:openstack_client].nova.get_server_details(env, server_id)['status']
      fail Errors::ServerStatusError, server: server_id if server_status == 'ERROR'
      sleep retry_interval
    end
  end
end