Class: VagrantPlugins::OpenStack::Action::CreateServer

Inherits:
Object
  • Object
show all
Includes:
Vagrant::Util::Retryable
Defined in:
lib/vagrant-openstack-plugin/action/create_server.rb

Overview

This creates the OpenStack server.

Instance Method Summary collapse

Constructor Details

#initialize(app, env) ⇒ CreateServer

Returns a new instance of CreateServer.



13
14
15
16
# File 'lib/vagrant-openstack-plugin/action/create_server.rb', line 13

def initialize(app, env)
  @app    = app
  @logger = Log4r::Logger.new("vagrant_openstack::action::create_server")
end

Instance Method Details

#call(env) ⇒ Object

Raises:



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/vagrant-openstack-plugin/action/create_server.rb', line 18

def call(env)
  # Get the configs
  config   = env[:machine].provider_config

  # Find the flavor
  env[:ui].info(I18n.t("vagrant_openstack.finding_flavor"))
  flavor = find_matching(env[:openstack_compute].flavors.all, config.flavor)
  raise Errors::NoMatchingFlavor if !flavor

  # Find the image
  env[:ui].info(I18n.t("vagrant_openstack.finding_image"))
  image = find_matching(env[:openstack_compute].images, config.image)
  raise Errors::NoMatchingImage if !image

  # Figure out the name for the server
  server_name = config.server_name || env[:machine].name

  # Build the options for launching...
  options = {
    :flavor_ref  => flavor.id,
    :image_ref   => image.id,
    :name        => server_name,
    :key_name    => config.keypair_name,
    :metadata    => config.,
    :user_data   => config.user_data,
    :security_groups => config.security_groups,
    :os_scheduler_hints => config.scheduler_hints,
    :availability_zone => config.availability_zone
  }
  
  # Fallback to only one network, otherwise `config.networks` overrides
  unless config.networks
    if config.network
      config.networks = [ config.network ]
    end
  end

  # Find networks if provided
  unless config.networks.empty?
    env[:ui].info(I18n.t("vagrant_openstack.finding_network"))
    options[:nics] = Array.new
    config.networks.each do |net|
      network = find_matching(env[:openstack_network].networks, net)
      options[:nics] << {"net_id" => network.id} if network
    end
    env[:ui].info("options[:nics]: #{options[:nics]}")
  end
  
  # Output the settings we're going to use to the user
  env[:ui].info(I18n.t("vagrant_openstack.launching_server"))
  env[:ui].info(" -- Flavor: #{flavor.name}")
  env[:ui].info(" -- Image: #{image.name}")
  env[:ui].info(" -- Name: #{server_name}")
  config.networks.each do |n|
    env[:ui].info(" -- Network: #{n}")
  end
  if config.security_groups
    env[:ui].info(" -- Security Groups: #{config.security_groups}")
  end

  # Create the server
  server = env[:openstack_compute].servers.create(options)

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

  # Wait for the server to finish building
  env[:ui].info(I18n.t("vagrant_openstack.waiting_for_build"))
  retryable(:on => Fog::Errors::TimeoutError, :tries => 200) do
    # If we're interrupted don't worry about waiting
    next if env[:interrupted]

    # Set the progress
    env[:ui].clear_line
    env[:ui].report_progress(server.progress, 100, false)

    # Wait for the server to be ready
    begin
      server.wait_for(5) { ready? }
      # Once the server is up and running assign a floating IP if we have one
      floating_ip = config.floating_ip
      # try to automatically allocate a floating IP
      if floating_ip && floating_ip.to_sym == :auto
        addresses = env[:openstack_compute].addresses
        puts addresses
        free_floating = addresses.find_index {|a| a.fixed_ip.nil?}
        if free_floating.nil?
          raise Errors::FloatingIPNotFound
        end
        floating_ip = addresses[free_floating].ip
      end
        
      if floating_ip
        env[:ui].info( "Using floating IP #{floating_ip}")
        floater = env[:openstack_compute].addresses.find { |thisone| thisone.ip.eql? floating_ip }
        floater.server = server
      end
      
      # store this so we can use it later
      env[:floating_ip] = floating_ip
      
    rescue RuntimeError => e
      # If we don't have an error about a state transition, then
      # we just move on.
      raise if e.message !~ /should have transitioned/
      raise Errors::CreateBadState, :state => server.state
    end
  end

  if !env[:interrupted]
    # Clear the line one more time so the progress is removed
    env[:ui].clear_line

    # Wait for SSH to become available
    env[:ui].info(I18n.t("vagrant_openstack.waiting_for_ssh"))
    while true
      begin
        # If we're interrupted then just back out
        break if env[:interrupted]
        break if env[:machine].communicate.ready?
      rescue Errno::ENETUNREACH, Errno::EHOSTUNREACH
      end
      sleep 2
    end

    env[:ui].info(I18n.t("vagrant_openstack.ready"))
  end

  @app.call(env)
end