Class: Chef::Provisioning::FogDriver::Providers::Scaleway

Inherits:
Driver
  • Object
show all
Defined in:
lib/chef/provisioning/fog_driver/providers/scaleway.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, from_provider, from_url, #image_for, inherited, #initialize, new, #provider, provider_class_for, #ready_machine, register_provider_class, #transport_for

Constructor Details

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

Class Method Details

.compute_options_for(provider, id, config) ⇒ Object



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
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 101

def self.compute_options_for(provider, id, config)
  new_compute_options = {}
  new_compute_options[:provider] = provider
  if id && id != ""
    org, region = id.split(":")
    new_compute_options[:scaleway_organization] = org
    new_compute_options[:scaleway_region] = region || "par1"
  end
  new_config = { driver_options: { compute_options: new_compute_options } }

  new_default_compute_options = {}
  new_defaults = {
    driver_options: { compute_options: new_default_compute_options },
    machine_options: { bootstrap_options: {} }
  }

  result = Cheffish::MergedConfig.new(new_config, config, new_defaults)

  credential = Fog.credentials
  new_default_compute_options[:scaleway_organization] ||= credential[:scaleway_organization]
  new_default_compute_options[:scaleway_token] ||= credential[:scaleway_token]

  id = [result[:driver_options][:compute_options][:scaleway_organization],
        result[:driver_options][:compute_options][:scaleway_region]].join(":")

  [result, id]
end

Instance Method Details

#attach_ip(server, floating_ip) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 156

def attach_ip(server, floating_ip)
  ip = server.service.ips.get(floating_ip)
  raise "Requested IP (#{floating_ip}) not found" if ip.nil?
  if ip.server && (ip.server.identity != server.identity)
    raise "Requested IP (#{floating_ip}) already attached"
  end

  if server.public_ip
    old_ip = server.public_ip
    Chef::Log.info "Server #{server.identity} already has IP #{old_ip.address}, removing it"
    old_ip.server = nil
    old_ip.save
  end

  ip.server = server
  ip.save
  server.reload
end

#attach_ip_from_pool(server, _pool) ⇒ Object

Scaleway only has one global pool.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 138

def attach_ip_from_pool(server, _pool)
  return server if server.public_ip

  Chef::Log.info "Scaleway has only one IP pool, ignoring pool argument"
  ip = server.service.ips.all.select { |ip| ip.address.nil? }.first
  if ip
    ip.server = server
    ip.save
    server.reload
  else
    # Allocate a new IP
    ip = server.service.ips.create
    ip.server = server
    ip.save
    server.reload
  end
end

#bootstrap_options_for(action_handler, machine_spec, machine_options) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 42

def bootstrap_options_for(action_handler, machine_spec, machine_options)
  opts = super
  opts[:tags] = opts[:tags].map { |key, value| [key, value].join("=") }

  # Let's fetch the id of the volumes if the user didn't provide it
  # Which probably means they were created in chef
  if opts[:volumes]
    managed_entry_store = machine_spec.managed_entry_store
    volumes = Marshal.load(Marshal.dump(opts[:volumes]))

    volumes.each do |_index, volume|
      next if volume[:id]
      volume_spec = managed_entry_store.get(:volume, volume[:name])
      unless volume_spec
        raise "Volume #{volume[:name]} unknown, create it or provide its id"
      end
      volume[:id] = volume_spec.reference["id"]
    end
    opts[:volumes] = volumes
  end
  opts
end

#converge_floating_ips(action_handler, machine_spec, machine_options, server) ⇒ Object



129
130
131
132
133
134
135
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 129

def converge_floating_ips(action_handler, machine_spec, machine_options, server)
  if server.dynamic_ip_required
    Chef::Log.info "Dynamic IP allocation has been enabled, not converging IPs"
  else
    super
  end
end

#convergence_strategy_for(machine_spec, machine_options) ⇒ Object



36
37
38
39
40
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 36

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

#create_volume(action_handler, volume_spec, volume_options) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 185

def create_volume(action_handler, volume_spec, volume_options)
  # Prevent destructive operations on volume_options.
  clean_volume_options = Marshal.load(Marshal.dump(volume_options))

  volume_spec.reference ||= {}
  volume_spec.reference.update(
    "driver_url" => driver_url,
    "driver_version" => FogDriver::VERSION,
    "creator" => creator,
    "allocated_at" => Time.now.to_i
  )

  description = ["Creating volume #{volume_spec.name}"]
  volume_options.each { |k, v| description << "  #{k}: #{v.inspect}" }

  action_handler.report_progress description
  if action_handler.should_perform_actions
    clean_volume_options["name"] = volume_spec.name

    volume = compute.volumes.create(clean_volume_options)

    volume_spec.reference.update(
      "id" => volume.id,
      "volume_type" => volume.volume_type,
      "size" => volume.size
    )
    volume_spec.save(action_handler)
    action_handler.performed_action "volume #{volume_spec.name} created as #{volume.id} on #{driver_url}"
  end
end

#creatorObject



32
33
34
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 32

def creator
  compute_options[:scaleway_organization]
end

#destroy_machine(action_handler, machine_spec, machine_options) ⇒ Object



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
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 65

def destroy_machine(action_handler, machine_spec, machine_options)
  server = server_for(machine_spec)
  if server
    action_handler.perform_action "destroy machine #{machine_spec.name} (#{machine_spec.reference['server_id']} at #{driver_url})" do
      # Scaleway's API fail if we try to stop/terminate an instance with
      # certains states
      if server.state == "running"
        server.stop
        server.wait_for { server.state != "running" }
      end
      %w{stopping starting}.each do |state|
        server.wait_for { server.state != state } if server.state == state
      end

      if server.state == "stopped"
        server.destroy
      else
        Chef.log.fatal "Server is in an unknown state (#{server.state})"
      end
      machine_spec.reference = nil
    end
  end
  strategy = ConvergenceStrategy::NoConverge.new(machine_options[:convergence_options], config)
  strategy.cleanup_convergence(action_handler, machine_spec)
end

#destroy_volume(action_handler, volume_spec, _volume_options) ⇒ Object



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 216

def destroy_volume(action_handler, volume_spec, _volume_options)
  volume = volume_for(volume_spec)

  if volume && action_handler.should_perform_actions
    begin
      msg = "destroyed volume #{volume_spec.name} at #{driver_url}"
      action_handler.perform_action msg do
        volume.destroy
        volume_spec.reference = nil
        volume_spec.save(action_handler)
      end
    rescue Fog::Scaleway::Compute::InvalidRequestError => e
      Chef::Log.error "Unable to destroy volume #{volume_spec.name} : #{e.message}"
    end
  end
end

#find_floating_ips(server, action_handler) ⇒ Object

Get the public IP if any



176
177
178
179
180
181
182
183
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 176

def find_floating_ips(server, action_handler)
  public_ips = []
  Retryable.retryable(RETRYABLE_OPTIONS) do |retries, _exception|
    action_handler.report_progress "Querying for public IP attached to server #{server.id}, API attempt #{retries + 1}/#{RETRYABLE_OPTIONS[:tries]} ..."
    public_ips << server.public_ip.address if server.public_ip
  end
  public_ips
end

#stop_machine(action_handler, machine_spec, _machine_options) ⇒ Object



91
92
93
94
95
96
97
98
99
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 91

def stop_machine(action_handler, machine_spec, _machine_options)
  server = server_for(machine_spec)
  if server && (server.state == "running")
    action_handler.perform_action "stop machine #{machine_spec.name} (#{server.id} at #{driver_url})" do
      server.poweroff(true)
      server.wait_for { server.state == "stopped" }
    end
  end
end

#volume_for(volume_spec) ⇒ Object



233
234
235
236
237
# File 'lib/chef/provisioning/fog_driver/providers/scaleway.rb', line 233

def volume_for(volume_spec)
  if volume_spec.reference
    compute.volumes.get(volume_spec.reference["id"])
  end
end