vagrant-openstack-provider 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -2
  3. data/CHANGELOG.md +22 -0
  4. data/Gemfile +8 -15
  5. data/Vagrantfile +12 -10
  6. data/gemfiles/latest_stable.gemfile +6 -16
  7. data/gemfiles/minimal_release.gemfile +10 -0
  8. data/gemfiles/previous_release.gemfile +6 -16
  9. data/lib/vagrant-openstack-provider/action/connect_openstack.rb +2 -1
  10. data/lib/vagrant-openstack-provider/action/create_server.rb +40 -248
  11. data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +30 -29
  12. data/lib/vagrant-openstack-provider/action/sync_folders.rb +19 -9
  13. data/lib/vagrant-openstack-provider/action/wait_accessible.rb +58 -0
  14. data/lib/vagrant-openstack-provider/action/wait_active.rb +5 -3
  15. data/lib/vagrant-openstack-provider/action/wait_stop.rb +5 -3
  16. data/lib/vagrant-openstack-provider/action.rb +19 -11
  17. data/lib/vagrant-openstack-provider/client/http_utils.rb +3 -2
  18. data/lib/vagrant-openstack-provider/client/neutron.rb +11 -1
  19. data/lib/vagrant-openstack-provider/client/nova.rb +49 -30
  20. data/lib/vagrant-openstack-provider/command/abstract_command.rb +10 -1
  21. data/lib/vagrant-openstack-provider/command/flavor_list.rb +1 -1
  22. data/lib/vagrant-openstack-provider/command/floatingip_list.rb +1 -1
  23. data/lib/vagrant-openstack-provider/command/image_list.rb +1 -1
  24. data/lib/vagrant-openstack-provider/command/main.rb +2 -1
  25. data/lib/vagrant-openstack-provider/command/network_list.rb +8 -2
  26. data/lib/vagrant-openstack-provider/command/reset.rb +21 -0
  27. data/lib/vagrant-openstack-provider/command/utils.rb +1 -1
  28. data/lib/vagrant-openstack-provider/command/volume_list.rb +1 -1
  29. data/lib/vagrant-openstack-provider/config.rb +16 -1
  30. data/lib/vagrant-openstack-provider/config_resolver.rb +262 -0
  31. data/lib/vagrant-openstack-provider/errors.rb +40 -0
  32. data/lib/vagrant-openstack-provider/plugin.rb +3 -3
  33. data/lib/vagrant-openstack-provider/utils.rb +21 -0
  34. data/lib/vagrant-openstack-provider/version.rb +1 -1
  35. data/locales/en.yml +35 -1
  36. data/spec/vagrant-openstack-provider/action/create_server_spec.rb +121 -368
  37. data/spec/vagrant-openstack-provider/action/delete_server_spec.rb +54 -0
  38. data/spec/vagrant-openstack-provider/action/message_spec.rb +34 -0
  39. data/spec/vagrant-openstack-provider/action/read_ssh_info_spec.rb +34 -17
  40. data/spec/vagrant-openstack-provider/action/read_state_spec.rb +70 -0
  41. data/spec/vagrant-openstack-provider/action/resume_server_spec.rb +50 -0
  42. data/spec/vagrant-openstack-provider/action/start_server_spec.rb +50 -0
  43. data/spec/vagrant-openstack-provider/action/stop_server_spec.rb +50 -0
  44. data/spec/vagrant-openstack-provider/action/suspend_server_spec.rb +50 -0
  45. data/spec/vagrant-openstack-provider/action/sync_folders_spec.rb +155 -0
  46. data/spec/vagrant-openstack-provider/action/wait_accessible_spec.rb +68 -0
  47. data/spec/vagrant-openstack-provider/action/wait_active_spec.rb +47 -0
  48. data/spec/vagrant-openstack-provider/action/wait_stop_spec.rb +47 -0
  49. data/spec/vagrant-openstack-provider/action_spec.rb +121 -0
  50. data/spec/vagrant-openstack-provider/client/cinder_spec.rb +1 -1
  51. data/spec/vagrant-openstack-provider/client/keystone_spec.rb +1 -1
  52. data/spec/vagrant-openstack-provider/client/neutron_spec.rb +37 -1
  53. data/spec/vagrant-openstack-provider/client/nova_spec.rb +60 -7
  54. data/spec/vagrant-openstack-provider/client/utils_spec.rb +1 -1
  55. data/spec/vagrant-openstack-provider/command/flavor_list_spec.rb +44 -0
  56. data/spec/vagrant-openstack-provider/command/floatingip_list_spec.rb +19 -2
  57. data/spec/vagrant-openstack-provider/command/image_list_spec.rb +48 -0
  58. data/spec/vagrant-openstack-provider/command/network_list_spec.rb +67 -0
  59. data/spec/vagrant-openstack-provider/command/reset_spec.rb +25 -0
  60. data/spec/vagrant-openstack-provider/command/volume_list_spec.rb +10 -2
  61. data/spec/vagrant-openstack-provider/config_resolver_spec.rb +680 -0
  62. data/spec/vagrant-openstack-provider/config_spec.rb +15 -1
  63. data/spec/vagrant-openstack-provider/spec_helper.rb +3 -0
  64. data/spec/vagrant-openstack-provider/utils_spec.rb +103 -0
  65. data/vagrant-openstack-provider.gemspec +4 -2
  66. metadata +78 -11
  67. data/Appraisals +0 -13
  68. data/gemfiles/oldest_current.gemfile +0 -20
@@ -1,20 +1,30 @@
1
1
  require 'log4r'
2
2
 
3
+ require 'vagrant-openstack-provider/config_resolver'
4
+ require 'vagrant-openstack-provider/utils'
5
+
3
6
  module VagrantPlugins
4
7
  module Openstack
5
8
  module Action
6
9
  # This action reads the SSH info for the machine and puts it into the
7
10
  # `:machine_ssh_info` key in the environment.
8
11
  class ReadSSHInfo
9
- def initialize(app, _env)
12
+ def initialize(app, _env, resolver = ConfigResolver.new, utils = Utils.new)
10
13
  @app = app
11
14
  @logger = Log4r::Logger.new('vagrant_openstack::action::read_ssh_info')
15
+ @resolver = resolver
16
+ @utils = utils
12
17
  end
13
18
 
14
19
  def call(env)
15
20
  @logger.info 'Reading SSH info'
16
- env[:machine_ssh_info] = read_ssh_info(env)
17
-
21
+ server_id = env[:machine].id.to_sym
22
+ SSHInfoHolder.instance.tap do |holder|
23
+ holder.synchronize do
24
+ holder.ssh_info[server_id] = read_ssh_info(env) if holder.ssh_info[server_id].nil?
25
+ env[:machine_ssh_info] = holder.ssh_info[server_id]
26
+ end
27
+ end
18
28
  @app.call(env)
19
29
  end
20
30
 
@@ -22,42 +32,33 @@ module VagrantPlugins
22
32
 
23
33
  def read_ssh_info(env)
24
34
  config = env[:machine].provider_config
35
+ env[:ui].warn('SSH is disabled in the provider config. The action you are attempting is likely to fail') if config.ssh_disabled
25
36
  hash = {
26
- host: get_ip_address(env),
27
- port: resolve_ssh_port(env),
28
- username: resolve_ssh_username(env)
37
+ host: @utils.get_ip_address(env),
38
+ port: @resolver.resolve_ssh_port(env),
39
+ username: @resolver.resolve_ssh_username(env)
29
40
  }
30
41
  hash[:private_key_path] = "#{env[:machine].data_dir}/#{get_keypair_name(env)}" unless config.keypair_name || config.public_key_path
42
+ # Should work silently when https://github.com/mitchellh/vagrant/issues/4637 is fixed
43
+ hash[:log_level] = 'ERROR'
31
44
  hash
32
45
  end
33
46
 
34
- def resolve_ssh_port(env)
35
- machine_config = env[:machine].config
36
- return machine_config.ssh.port if machine_config.ssh.port
37
- 22
47
+ def get_keypair_name(env)
48
+ env[:openstack_client].nova.get_server_details(env, env[:machine].id)['key_name']
38
49
  end
50
+ end
39
51
 
40
- def resolve_ssh_username(env)
41
- config = env[:machine].provider_config
42
- machine_config = env[:machine].config
43
- return machine_config.ssh.username if machine_config.ssh.username
44
- return config.ssh_username if config.ssh_username
45
- fail Errors::NoMatchingSshUsername
46
- end
52
+ class SSHInfoHolder < Mutex
53
+ include Singleton
47
54
 
48
- def get_ip_address(env)
49
- return env[:machine].provider_config.floating_ip unless env[:machine].provider_config.floating_ip.nil?
50
- details = env[:openstack_client].nova.get_server_details(env, env[:machine].id)
51
- details['addresses'].each do |network|
52
- network[1].each do |network_detail|
53
- return network_detail['addr'] if network_detail['OS-EXT-IPS:type'] == 'floating'
54
- end
55
- end
56
- fail Errors::UnableToResolveIP
57
- end
55
+ #
56
+ # Keys are machine ids
57
+ #
58
+ attr_accessor :ssh_info
58
59
 
59
- def get_keypair_name(env)
60
- env[:openstack_client].nova.get_server_details(env, env[:machine].id)['key_name']
60
+ def initialize
61
+ @ssh_info = {}
61
62
  end
62
63
  end
63
64
  end
@@ -12,10 +12,11 @@ module VagrantPlugins
12
12
 
13
13
  def call(env)
14
14
  sync_method = env[:machine].provider_config.sync_method
15
- if sync_method == 'rsync'
15
+ ssh_disabled = env[:machine].provider_config.ssh_disabled
16
+ if sync_method == 'none' || ssh_disabled
17
+ NoSyncFolders.new(@app, env, ssh_disabled).call(env)
18
+ elsif sync_method == 'rsync'
16
19
  RsyncFolders.new(@app, env).call(env)
17
- elsif sync_method == 'none'
18
- NoSyncFolders.new(@app, env).call(env)
19
20
  else
20
21
  fail Errors::SyncMethodError, sync_method_value: sync_method
21
22
  end
@@ -23,13 +24,15 @@ module VagrantPlugins
23
24
  end
24
25
 
25
26
  class NoSyncFolders
26
- def initialize(app, _env)
27
+ def initialize(app, _env, ssh_disabled)
27
28
  @app = app
29
+ @ssh_disabled = ssh_disabled
28
30
  end
29
31
 
30
32
  def call(env)
31
33
  @app.call(env)
32
- env[:ui].info('Sync folders are disabled')
34
+ env[:ui].info('Folders will not be synced because provider config ssh_disabled is set to true') if @ssh_disabled
35
+ env[:ui].info('Sync folders are disabled in the provider configuration') unless @ssh_disabled
33
36
  end
34
37
  end
35
38
 
@@ -60,15 +63,14 @@ module VagrantPlugins
60
63
 
61
64
  # If on Windows, modify the path to work with cygwin rsync
62
65
  if @host_os =~ /mswin|mingw|cygwin/
63
- hostpath = hostpath.sub(/^([A-Za-z]):\//, "/cygdrive/#{Regexp.last_match[1].downcase}/")
66
+ hostpath = add_cygdrive_prefix_to_path(hostpath)
64
67
  end
65
68
 
66
69
  env[:ui].info(I18n.t('vagrant_openstack.rsync_folder', hostpath: hostpath, guestpath: guestpath))
67
70
 
68
71
  # Create the guest path
69
72
  env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
70
- env[:machine].communicate.sudo(
71
- "chown -R #{ssh_info[:username]} '#{guestpath}'")
73
+ env[:machine].communicate.sudo("chown -R #{ssh_info[:username]} '#{guestpath}'")
72
74
 
73
75
  # Generate rsync include commands
74
76
  includes = rsync_includes.each_with_object([]) do |incl, incls|
@@ -77,12 +79,14 @@ module VagrantPlugins
77
79
  end
78
80
 
79
81
  # Rsync over to the guest path using the SSH info. add
80
- # .hg/ to exclude list as that isn't covered in
82
+ # .hg/ and .git/ to exclude list as that isn't covered in
81
83
  # --cvs-exclude
82
84
  command = [
83
85
  'rsync', '--verbose', '--archive', '-z',
84
86
  '--cvs-exclude',
85
87
  '--exclude', '.hg/',
88
+ '--exclude', '.git/',
89
+ '--chmod', 'ugo=rwX',
86
90
  *includes,
87
91
  '-e', "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no #{ssh_key_options(ssh_info)}",
88
92
  hostpath,
@@ -109,6 +113,12 @@ module VagrantPlugins
109
113
  # Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
110
114
  Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
111
115
  end
116
+
117
+ def add_cygdrive_prefix_to_path(hostpath)
118
+ hostpath.downcase.sub(/^([a-z]):\//) do
119
+ "/cygdrive/#{Regexp.last_match[1]}/"
120
+ end
121
+ end
112
122
  end
113
123
  end
114
124
  end
@@ -0,0 +1,58 @@
1
+ require 'log4r'
2
+
3
+ module VagrantPlugins
4
+ module Openstack
5
+ module Action
6
+ class WaitForServerToBeAccessible
7
+ def initialize(app, env, resolver = nil, ssh = nil)
8
+ @logger = Log4r::Logger.new('vagrant_openstack::action::wait_accessible')
9
+ @app = app
10
+ @ssh = ssh || Vagrant::Action::Builtin::SSHRun.new(app, env)
11
+ @resolver = resolver || VagrantPlugins::Openstack::ConfigResolver.new
12
+ end
13
+
14
+ def call(env)
15
+ waiting_for_server_to_be_reachable(env)
16
+ @logger.info 'The server is ready'
17
+ env[:ui].info(I18n.t('vagrant_openstack.ready'))
18
+ @app.call(env)
19
+ end
20
+
21
+ private
22
+
23
+ def waiting_for_server_to_be_reachable(env)
24
+ return if env[:interrupted]
25
+ ssh_timeout = env[:machine].provider_config.ssh_timeout
26
+ return if server_is_reachable?(env, ssh_timeout)
27
+ env[:ui].error(I18n.t('vagrant_openstack.timeout'))
28
+ fail Errors::SshUnavailable, host: @resolver.resolve_floating_ip(env), timeout: ssh_timeout
29
+ end
30
+
31
+ def server_is_reachable?(env, timeout)
32
+ start_time = Time.now
33
+ current_time = start_time
34
+ nb_retry = 0
35
+
36
+ while (current_time - start_time) <= timeout
37
+ @logger.debug "Checking if SSH port is open... Attempt number #{nb_retry}"
38
+ if nb_retry % 5 == 0
39
+ @logger.info 'Waiting for SSH to become available...'
40
+ env[:ui].info(I18n.t('vagrant_openstack.waiting_for_ssh'))
41
+ end
42
+
43
+ env[:ssh_run_command] = 'exit 0'
44
+ @ssh.call(env)
45
+ return true if env[:ssh_run_exit_status] == 0
46
+
47
+ @logger.debug 'SSH not yet available... new retry in in 1 second'
48
+ nb_retry += 1
49
+ sleep 1
50
+ current_time = Time.now
51
+ end
52
+
53
+ false
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -5,18 +5,20 @@ module VagrantPlugins
5
5
  module Openstack
6
6
  module Action
7
7
  class WaitForServerToBeActive
8
- def initialize(app, _env)
8
+ def initialize(app, _env, retry_interval = 3, timeout = 200)
9
9
  @app = app
10
10
  @logger = Log4r::Logger.new('vagrant_openstack::action::start_server')
11
+ @retry_interval = retry_interval
12
+ @timeout = timeout
11
13
  end
12
14
 
13
15
  def call(env)
14
16
  if env[:machine].id
15
17
  env[:ui].info(I18n.t('vagrant_openstack.waiting_start'))
16
18
  client = env[:openstack_client].nova
17
- timeout(200) do
19
+ timeout(@timeout) do
18
20
  while client.get_server_details(env, env[:machine].id)['status'] != 'ACTIVE'
19
- sleep 3
21
+ sleep @retry_interval
20
22
  @logger.info('Waiting for server to be active')
21
23
  end
22
24
  end
@@ -5,18 +5,20 @@ module VagrantPlugins
5
5
  module Openstack
6
6
  module Action
7
7
  class WaitForServerToStop
8
- def initialize(app, _env)
8
+ def initialize(app, _env, retry_interval = 3, timeout = 200)
9
9
  @app = app
10
10
  @logger = Log4r::Logger.new('vagrant_openstack::action::stop_server')
11
+ @retry_interval = retry_interval
12
+ @timeout = timeout
11
13
  end
12
14
 
13
15
  def call(env)
14
16
  if env[:machine].id
15
17
  env[:ui].info(I18n.t('vagrant_openstack.waiting_stop'))
16
18
  client = env[:openstack_client].nova
17
- timeout(200) do
19
+ timeout(@timeout) do
18
20
  while client.get_server_details(env, env[:machine].id)['status'] != 'SHUTOFF'
19
- sleep 3
21
+ sleep @retry_interval
20
22
  @logger.info('Waiting for server to stop')
21
23
  end
22
24
  end
@@ -10,7 +10,7 @@ module VagrantPlugins
10
10
 
11
11
  # This action is called to destroy the remote machine.
12
12
  def self.action_destroy
13
- Vagrant::Action::Builder.new.tap do |b|
13
+ new_builder.tap do |b|
14
14
  b.use ConfigValidate
15
15
  b.use ConnectOpenstack
16
16
  b.use Call, ReadState do |env, b2|
@@ -25,7 +25,7 @@ module VagrantPlugins
25
25
 
26
26
  # This action is called when `vagrant provision` is called.
27
27
  def self.action_provision
28
- Vagrant::Action::Builder.new.tap do |b|
28
+ new_builder.tap do |b|
29
29
  b.use ConfigValidate
30
30
  b.use ConnectOpenstack
31
31
  b.use Call, ReadState do |env, b2|
@@ -43,7 +43,7 @@ module VagrantPlugins
43
43
  # resulting state is expected to be put into the `:machine_ssh_info`
44
44
  # key.
45
45
  def self.action_read_ssh_info
46
- Vagrant::Action::Builder.new.tap do |b|
46
+ new_builder.tap do |b|
47
47
  b.use ConfigValidate
48
48
  b.use ConnectOpenstack
49
49
  b.use ReadSSHInfo
@@ -54,7 +54,7 @@ module VagrantPlugins
54
54
  # resulting state is expected to be put into the `:machine_state_id`
55
55
  # key.
56
56
  def self.action_read_state
57
- Vagrant::Action::Builder.new.tap do |b|
57
+ new_builder.tap do |b|
58
58
  b.use ConfigValidate
59
59
  b.use ConnectOpenstack
60
60
  b.use ReadState
@@ -62,7 +62,7 @@ module VagrantPlugins
62
62
  end
63
63
 
64
64
  def self.action_ssh
65
- Vagrant::Action::Builder.new.tap do |b|
65
+ new_builder.tap do |b|
66
66
  b.use ConfigValidate
67
67
  b.use ConnectOpenstack
68
68
  b.use Call, ReadState do |env, b2|
@@ -76,7 +76,7 @@ module VagrantPlugins
76
76
  end
77
77
 
78
78
  def self.action_ssh_run
79
- Vagrant::Action::Builder.new.tap do |b|
79
+ new_builder.tap do |b|
80
80
  b.use ConfigValidate
81
81
  b.use ConnectOpenstack
82
82
  b.use Call, ReadState do |env, b2|
@@ -90,7 +90,7 @@ module VagrantPlugins
90
90
  end
91
91
 
92
92
  def self.action_up
93
- Vagrant::Action::Builder.new.tap do |b|
93
+ new_builder.tap do |b|
94
94
  b.use ConfigValidate
95
95
  b.use ConnectOpenstack
96
96
 
@@ -100,6 +100,7 @@ module VagrantPlugins
100
100
  b2.use Provision
101
101
  b2.use SyncFolders
102
102
  b2.use CreateServer
103
+ b2.use WaitForServerToBeAccessible
103
104
  when :shutoff
104
105
  b2.use StartServer
105
106
  when :suspended
@@ -112,7 +113,7 @@ module VagrantPlugins
112
113
  end
113
114
 
114
115
  def self.action_halt
115
- Vagrant::Action::Builder.new.tap do |b|
116
+ new_builder.tap do |b|
116
117
  b.use ConfigValidate
117
118
  b.use ConnectOpenstack
118
119
  b.use Call, ReadState do |env, b2|
@@ -128,7 +129,7 @@ module VagrantPlugins
128
129
  # This is the action that is primarily responsible for suspending
129
130
  # the virtual machine.
130
131
  def self.action_suspend
131
- Vagrant::Action::Builder.new.tap do |b|
132
+ new_builder.tap do |b|
132
133
  b.use ConfigValidate
133
134
  b.use ConnectOpenstack
134
135
  b.use Call, ReadState do |env, b2|
@@ -146,7 +147,7 @@ module VagrantPlugins
146
147
  # This is the action that is primarily responsible for resuming
147
148
  # suspended machines.
148
149
  def self.action_resume
149
- Vagrant::Action::Builder.new.tap do |b|
150
+ new_builder.tap do |b|
150
151
  b.use ConfigValidate
151
152
  b.use ConnectOpenstack
152
153
  b.use Call, ReadState do |env, b2|
@@ -160,7 +161,7 @@ module VagrantPlugins
160
161
  end
161
162
 
162
163
  def self.action_reload
163
- Vagrant::Action::Builder.new.tap do |b|
164
+ new_builder.tap do |b|
164
165
  b.use ConfigValidate
165
166
  b.use ConnectOpenstack
166
167
  b.use Call, ReadState do |env, b2|
@@ -199,6 +200,13 @@ module VagrantPlugins
199
200
  autoload :Resume, action_root.join('resume')
200
201
  autoload :WaitForServerToStop, action_root.join('wait_stop')
201
202
  autoload :WaitForServerToBeActive, action_root.join('wait_active')
203
+ autoload :WaitForServerToBeAccessible, action_root.join('wait_accessible')
204
+
205
+ private
206
+
207
+ def self.new_builder
208
+ Vagrant::Action::Builder.new
209
+ end
202
210
  end
203
211
  end
204
212
  end
@@ -72,9 +72,10 @@ module VagrantPlugins
72
72
  when 401
73
73
  fail Errors::AuthenticationRequired
74
74
  when 400, 404, 409
75
- fail Errors::VagrantOpenstackError, message: JSON.parse(response.to_s)[ERRORS[response.code.to_s]]['message']
75
+ message = JSON.parse(response.to_s)[ERRORS[response.code.to_s]]['message']
76
+ fail Errors::VagrantOpenstackError, message: message, code: response.code
76
77
  else
77
- fail Errors::VagrantOpenstackError, message: response.to_s
78
+ fail Errors::VagrantOpenstackError, message: response.to_s, code: response.code
78
79
  end
79
80
  end
80
81
 
@@ -33,10 +33,20 @@ module VagrantPlugins
33
33
  end
34
34
 
35
35
  def get_private_networks(env)
36
+ get_networks(env, false)
37
+ end
38
+
39
+ def get_all_networks(env)
40
+ get_networks(env, true)
41
+ end
42
+
43
+ private
44
+
45
+ def get_networks(env, all)
36
46
  networks_json = get(env, "#{@session.endpoints[:network]}/networks")
37
47
  networks = []
38
48
  JSON.parse(networks_json)['networks'].each do |n|
39
- networks << Item.new(n['id'], n['name']) if n['tenant_id'].eql? @session.project_id
49
+ networks << Item.new(n['id'], n['name']) if all || n['tenant_id'].eql?(@session.project_id)
40
50
  end
41
51
  networks
42
52
  end
@@ -27,7 +27,7 @@ module VagrantPlugins
27
27
  def get_all_floating_ips(env)
28
28
  ips_json = get(env, "#{@session.endpoints[:compute]}/os-floating-ips",
29
29
  'X-Auth-Token' => @session.token,
30
- :accept => :json) { |res| handle_response(res) }
30
+ :accept => :json)
31
31
  JSON.parse(ips_json)['floating_ips'].map { |n| FloatingIP.new(n['ip'], n['pool'], n['instance_id']) }
32
32
  end
33
33
 
@@ -38,7 +38,7 @@ module VagrantPlugins
38
38
  }.to_json,
39
39
  'X-Auth-Token' => @session.token,
40
40
  :accept => :json,
41
- :content_type => :json) { |res| handle_response(res) }
41
+ :content_type => :json)
42
42
  floating_ip = JSON.parse(ips_json)['floating_ip']
43
43
  FloatingIP.new(floating_ip['ip'], floating_ip['pool'], floating_ip['instance_id'])
44
44
  end
@@ -60,14 +60,9 @@ module VagrantPlugins
60
60
  s['key_name'] = options[:keypair]
61
61
  s['availability_zone'] = options[:availability_zone] unless options[:availability_zone].nil?
62
62
  s['security_groups'] = options[:security_groups] unless options[:security_groups].nil?
63
- s['user_data'] = options[:user_data] unless options[:user_data].nil?
63
+ s['user_data'] = Base64.encode64(options[:user_data]) unless options[:user_data].nil?
64
64
  s['metadata'] = options[:metadata] unless options[:metadata].nil?
65
- unless options[:networks].nil? || options[:networks].empty?
66
- s['networks'] = []
67
- options[:networks].each do |uuid|
68
- s['networks'] << { uuid: uuid }
69
- end
70
- end
65
+ s['networks'] = options[:networks] unless options[:networks].nil? || options[:networks].empty?
71
66
  end
72
67
  object = { server: server }
73
68
  object[:scheduler_hints] = options[:scheduler_hints] unless options[:scheduler_hints].nil?
@@ -76,36 +71,49 @@ module VagrantPlugins
76
71
  end
77
72
 
78
73
  def delete_server(env, server_id)
79
- delete(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
74
+ instance_exists do
75
+ delete(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
76
+ end
80
77
  end
81
78
 
82
79
  def suspend_server(env, server_id)
83
- change_server_state(env, server_id, :suspend)
80
+ instance_exists do
81
+ change_server_state(env, server_id, :suspend)
82
+ end
84
83
  end
85
84
 
86
85
  def resume_server(env, server_id)
87
- # TODO(julienvey) check status before (if pause->unpause, if suspend->resume...)
88
- change_server_state(env, server_id, :resume)
86
+ instance_exists do
87
+ change_server_state(env, server_id, :resume)
88
+ end
89
89
  end
90
90
 
91
91
  def stop_server(env, server_id)
92
- change_server_state(env, server_id, :stop)
92
+ instance_exists do
93
+ change_server_state(env, server_id, :stop)
94
+ end
93
95
  end
94
96
 
95
97
  def start_server(env, server_id)
96
- change_server_state(env, server_id, :start)
98
+ instance_exists do
99
+ change_server_state(env, server_id, :start)
100
+ end
97
101
  end
98
102
 
99
103
  def get_server_details(env, server_id)
100
- server_details = get(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
101
- JSON.parse(server_details)['server']
104
+ instance_exists do
105
+ server_details = get(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
106
+ JSON.parse(server_details)['server']
107
+ end
102
108
  end
103
109
 
104
110
  def add_floating_ip(env, server_id, floating_ip)
105
- check_floating_ip(env, floating_ip)
111
+ instance_exists do
112
+ check_floating_ip(env, floating_ip)
106
113
 
107
- post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
108
- { addFloatingIp: { address: floating_ip } }.to_json)
114
+ post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
115
+ { addFloatingIp: { address: floating_ip } }.to_json)
116
+ end
109
117
  end
110
118
 
111
119
  def import_keypair(env, public_key)
@@ -128,8 +136,10 @@ module VagrantPlugins
128
136
  end
129
137
 
130
138
  def delete_keypair_if_vagrant(env, server_id)
131
- keyname = get_server_details(env, server_id)['key_name']
132
- delete(env, "#{@session.endpoints[:compute]}/os-keypairs/#{keyname}") if keyname.start_with?('vagrant-generated-')
139
+ instance_exists do
140
+ keyname = get_server_details(env, server_id)['key_name']
141
+ delete(env, "#{@session.endpoints[:compute]}/os-keypairs/#{keyname}") if keyname.start_with?('vagrant-generated-')
142
+ end
133
143
  end
134
144
 
135
145
  def get_floating_ip_pools(env)
@@ -143,14 +153,16 @@ module VagrantPlugins
143
153
  end
144
154
 
145
155
  def attach_volume(env, server_id, volume_id, device = nil)
146
- attachment = post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/os-volume_attachments",
147
- {
148
- volumeAttachment: {
149
- volumeId: volume_id,
150
- device: device
151
- }
152
- }.to_json)
153
- JSON.parse(attachment)['volumeAttachment']
156
+ instance_exists do
157
+ attachment = post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/os-volume_attachments",
158
+ {
159
+ volumeAttachment: {
160
+ volumeId: volume_id,
161
+ device: device
162
+ }
163
+ }.to_json)
164
+ JSON.parse(attachment)['volumeAttachment']
165
+ end
154
166
  end
155
167
 
156
168
  private
@@ -163,6 +175,13 @@ module VagrantPlugins
163
175
  stop: 'os-stop'
164
176
  }
165
177
 
178
+ def instance_exists
179
+ return yield
180
+ rescue Errors::VagrantOpenstackError => e
181
+ raise Errors::InstanceNotFound if e.extra_data[:code] == 404
182
+ raise e
183
+ end
184
+
166
185
  def change_server_state(env, server_id, new_state)
167
186
  post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
168
187
  { :"#{VM_STATES[new_state.to_sym]}" => nil }.to_json)