Class: Chef::Provisioning::FogDriver::Providers::OpenStack

Inherits:
Driver
  • Object
show all
Defined in:
lib/chef/provisioning/fog_driver/providers/openstack.rb

Constant Summary

Constants inherited from Driver

Driver::DEFAULT_OPTIONS, Driver::RETRYABLE_ERRORS, Driver::RETRYABLE_OPTIONS

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Driver

__new__, #allocate_machine, #allocate_machines, canonicalize_url, #compute, #compute_options, #connect_to_machine, #create_volume, #destroy_machine, #destroy_volume, from_provider, from_url, inherited, #initialize, new, #provider, provider_class_for, #ready_machine, register_provider_class, #stop_machine, #transport_for

Constructor Details

This class inherits a constructor from Chef::Provisioning::FogDriver::Driver

Class Method Details

.compute_options_for(provider, id, config) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 38

def self.compute_options_for(provider, id, config)
  new_compute_options = {}
  new_compute_options[:provider] = provider
  new_config = { driver_options: { compute_options: new_compute_options } }
  new_defaults = {
    driver_options: { compute_options: {} },
    machine_options: { bootstrap_options: {} }
  }
  result = Cheffish::MergedConfig.new(new_config, config, new_defaults)

  new_compute_options[:openstack_auth_url] = id if id && id != ""

  credential = Fog.credentials.find_all do |k, _v|
    k.to_s.start_with?("openstack")
  end
  credential.each do |k, v|
    new_compute_options[k] ||= v
  end

  id = result[:driver_options][:compute_options][:openstack_auth_url]

  [result, id]
end

Instance Method Details

#allocate_image(action_handler, image_spec, image_options, machine_spec, _machine_options) ⇒ Object

Image methods



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 63

def allocate_image(action_handler, image_spec, image_options, machine_spec, _machine_options)
  image = image_for(image_spec)
  if image
    raise "The image already exists, why are you asking me to create it?  I can't do that, Dave."
  end
  action_handler.perform_action "Create image #{image_spec.name} from machine #{machine_spec.name} with options #{image_options.inspect}" do
    response = compute.create_image(
      machine_spec.reference["server_id"], image_spec.name,
      description: "The Image named '#{image_spec.name}"
    )

    image_spec.reference = {
      driver_url: driver_url,
      driver_version: FogDriver::VERSION,
      image_id: response.body["image"]["id"],
      creator: creator,
      allocated_it: Time.new.to_i
    }
  end
end

#convergence_strategy_for(machine_spec, machine_options) ⇒ Object



13
14
15
16
17
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 13

def convergence_strategy_for(machine_spec, machine_options)
  machine_options = Cheffish::MergedConfig.new(machine_options,
                                               convergence_options: { ohai_hints: { "openstack" => {} } })
  super(machine_spec, machine_options)
end

#create_winrm_transport(machine_spec, machine_options, server) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 19

def create_winrm_transport(machine_spec, machine_options, server)
  if machine_options[:winrm].nil?
    raise "You must provide winrm settings in machine_options to use the winrm transport!"
  end
  remote_host = determine_remote_host machine_spec, server
  Chef::Log.info("Connecting to server #{remote_host}")
  port = machine_options[:winrm][:port] || 5985
  endpoint = "http://#{remote_host}:#{port}/wsman"
  type = machine_options[:winrm][:type] || :negotiate
  decrypted_password = machine_options[:winrm][:password] || ""
  options = {
    user: machine_options[:winrm][:username] || "Administrator",
    pass: decrypted_password,
    disable_sspi: !!machine_options[:winrm][:disable_sspi] || false,
    basic_auth_only: !!machine_options[:winrm][:basic_auth_only] || false
  }
  Chef::Provisioning::Transport::WinRM.new(endpoint, type, options, {})
end

#creatorObject



9
10
11
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 9

def creator
  compute_options[:openstack_username]
end

#destroy_image(_action_handler, image_spec, _image_options) ⇒ Object



98
99
100
101
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 98

def destroy_image(_action_handler, image_spec, _image_options)
  image = image_for(image_spec)
  image.destroy unless image.status == "DELETED"
end

#determine_remote_host(machine_spec, server) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 133

def determine_remote_host(machine_spec, server)
  transport_address_location = (machine_spec.reference["transport_address_location"] || :none).to_sym

  if machine_spec.reference["use_private_ip_for_ssh"]
    # The machine_spec has the old config key, lets update it - a successful chef converge will save the machine_spec
    # TODO in 2.0 get rid of this update
    machine_spec.reference.delete("use_private_ip_for_ssh")
    machine_spec.reference["transport_address_location"] = :private_ip
    server.private_ip_address
  elsif transport_address_location == :ip_addresses
    server.ip_addresses.first
  elsif transport_address_location == :private_ip
    server.private_ip_address
  elsif transport_address_location == :public_ip
    server.public_ip_address
  elsif !server.public_ip_address && server.private_ip_address
    Chef::Log.warn("Server #{machine_spec.name} has no public floating_ip address.  Using private floating_ip '#{server.private_ip_address}'.  Set driver option 'transport_address_location' => :private_ip if this will always be the case ...")
    server.private_ip_address
  elsif server.public_ip_address
    server.public_ip_address
  else
    raise "Server #{server.id} has no private or public IP address!"
    # raise "Invalid 'transport_address_location'.  They can only be 'public_ip', 'private_ip', or 'ip_addresses'."
  end
end

#image_for(image_spec) ⇒ Object



127
128
129
130
131
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 127

def image_for(image_spec)
  if image_spec.reference
    compute.images.get(image_spec.reference[:image_id]) || compute.images.get(image_spec.reference["image_id"])
  end
end

#ready_image(action_handler, image_spec, _image_options) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 84

def ready_image(action_handler, image_spec, _image_options)
  actual_image = image_for(image_spec)
  if actual_image.nil?
    raise "Cannot ready an image that does not exist"
  else
    if actual_image.status != "ACTIVE"
      action_handler.report_progress "Waiting for image to be active ..."
      wait_until_ready_image(action_handler, image_spec, actual_image)
    else
      action_handler.report_progress "Image #{image_spec.name} is active!"
    end
  end
end

#wait_until_image(action_handler, image_spec, image = nil) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 107

def wait_until_image(action_handler, image_spec, image = nil)
  image ||= image_for(image_spec)
  time_elapsed = 0
  sleep_time = 10
  max_wait_time = 300
  unless yield(image)
    action_handler.report_progress "waiting for image #{image_spec.name} (#{image.id} on #{driver_url}) to be active ..."
    while time_elapsed < max_wait_time && !yield(image)
      action_handler.report_progress "been waiting #{time_elapsed}/#{max_wait_time} -- sleeping #{sleep_time} seconds for image #{image_spec.name} (#{image.id} on #{driver_url}) to be ACTIVE instead of #{image.status}..."
      sleep(sleep_time)
      image.reload
      time_elapsed += sleep_time
    end
    unless yield(image)
      raise "Image #{image.id} did not become ready within #{max_wait_time} seconds"
    end
    action_handler.report_progress "Image #{image_spec.name} is now ready"
  end
end

#wait_until_ready_image(action_handler, image_spec, image = nil) ⇒ Object



103
104
105
# File 'lib/chef/provisioning/fog_driver/providers/openstack.rb', line 103

def wait_until_ready_image(action_handler, image_spec, image = nil)
  wait_until_image(action_handler, image_spec, image) { image.status == "ACTIVE" }
end