vagrant-conoha 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -1
  3. data/CHANGELOG.md +3 -0
  4. data/Vagrantfile +9 -0
  5. data/lib/vagrant-conoha/action.rb +82 -0
  6. data/lib/vagrant-conoha/action/create_server.rb +30 -2
  7. data/lib/vagrant-conoha/action/read_ssh_info.rb +3 -1
  8. data/lib/vagrant-conoha/action/snapshot_cleanup.rb +32 -0
  9. data/lib/vagrant-conoha/action/snapshot_delete.rb +32 -0
  10. data/lib/vagrant-conoha/action/snapshot_list.rb +22 -0
  11. data/lib/vagrant-conoha/action/snapshot_restore.rb +29 -0
  12. data/lib/vagrant-conoha/action/snapshot_save.rb +51 -0
  13. data/lib/vagrant-conoha/action/sync_folders.rb +0 -18
  14. data/lib/vagrant-conoha/cap/snapshot_list.rb +15 -0
  15. data/lib/vagrant-conoha/client/domain.rb +6 -2
  16. data/lib/vagrant-conoha/client/nova.rb +95 -4
  17. data/lib/vagrant-conoha/client/rest_utils.rb +6 -3
  18. data/lib/vagrant-conoha/config.rb +26 -4
  19. data/lib/vagrant-conoha/config_resolver.rb +20 -0
  20. data/lib/vagrant-conoha/version.rb +1 -1
  21. data/locales/en.yml +2 -0
  22. data/spec/vagrant-conoha/action/create_server_spec.rb +1 -1
  23. data/spec/vagrant-conoha/action/read_ssh_info_spec.rb +11 -0
  24. data/spec/vagrant-conoha/client/cinder_spec.rb +2 -0
  25. data/spec/vagrant-conoha/client/glance_spec.rb +2 -0
  26. data/spec/vagrant-conoha/client/heat_spec.rb +2 -0
  27. data/spec/vagrant-conoha/client/keystone_spec.rb +2 -0
  28. data/spec/vagrant-conoha/client/neutron_spec.rb +2 -0
  29. data/spec/vagrant-conoha/client/nova_spec.rb +6 -3
  30. data/spec/vagrant-conoha/config_resolver_spec.rb +11 -0
  31. data/spec/vagrant-conoha/config_spec.rb +14 -1
  32. metadata +8 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5f6d8e918ef420c86161b4975201a0c2a8a7f57
4
- data.tar.gz: bfed2b1a52dd42baabdc1d9bea2517372fa166ca
3
+ metadata.gz: 2c29698b0a2fe6b73bc0c0aa25018eba9983b07c
4
+ data.tar.gz: 1894ed5c1de790b660ba5a9d7e8d0857528dedaf
5
5
  SHA512:
6
- metadata.gz: aa75a9dbdcc1ee891f3b47b7dfea65f4a92790ca6d65e1e49550982da4525e232df65e25c90e202d604c8d5b6b54f1b06d4335f1ca9734f6c115ee8701f43cd4
7
- data.tar.gz: 5cd9d0b742944b21262f159c4fc45d0861391162959c35565fde7e3842102e0aabfaabbde21acb7384aa440fe9c06543d19436879d46f0d7d39a899f3b102302
6
+ metadata.gz: 958d00ad314df677595e667229d8a0520f98f4e7d5138118f2d1135e6daeefd9fe7f01954ffb80fd6f1617fceb8615f6c08293895c893f1ef5c3c0893e71ed68
7
+ data.tar.gz: 786d1afd0eceaff4336b9b4d757140f5cbf165c61acdc105e1a597ef604ae099105ad396b76a57805659a1dccc62bafba15361adeadef2c9952beaa79b35a51f
@@ -3,6 +3,7 @@ AllCops:
3
3
  - '.bundle/**/*'
4
4
  - 'out/**/*'
5
5
  - '**/Vagrantfile'
6
+ DisplayCopNames: true
6
7
 
7
8
  Style/FileName:
8
9
  Enabled: false
@@ -24,7 +25,7 @@ Metrics/CyclomaticComplexity:
24
25
  Max: 15
25
26
 
26
27
  Metrics/MethodLength:
27
- Max: 60
28
+ Max: 65
28
29
 
29
30
  Metrics/LineLength:
30
31
  Max: 150
@@ -1,3 +1,6 @@
1
+ # 0.1.8
2
+ - upstream(0.10.0)に追従した
3
+
1
4
  # 0.1.7
2
5
  - upstream(0.9)に追従した
3
6
 
@@ -96,6 +96,15 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
96
96
  #
97
97
  # conoha.keypair_name = "my-keypair"
98
98
 
99
+ # スタートアップスクリプトを指定します。
100
+ # cloud-config形式、シェルスクリプト形式、どちらでも記述できます。
101
+ # Base64エンコードする必要はありません。
102
+ #
103
+ # 詳細は下記URLを参考にしてください。
104
+ # https://www.conoha.jp/guide/startupscript.php
105
+ #
106
+ # conoha.user_data = ""
107
+
99
108
  end
100
109
 
101
110
  # すでにSSH公開鍵をコントロールパネルに登録している場合は、
@@ -18,6 +18,7 @@ module VagrantPlugins
18
18
  b2.use Message, I18n.t('vagrant_openstack.not_created')
19
19
  else
20
20
  b2.use(ProvisionerCleanup, :before)
21
+ b2.use SnapshotCleanup if Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('1.8.0')
21
22
  b2.use DeleteServer
22
23
  b2.use DeleteStack
23
24
  end
@@ -233,6 +234,77 @@ module VagrantPlugins
233
234
  end
234
235
  end
235
236
 
237
+ # TODO: Remove the if guard when Vagrant 1.8.0 is the minimum version.
238
+ # rubocop:disable IndentationWidth
239
+ if Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('1.8.0')
240
+ def self.action_snapshot_delete
241
+ new_builder.tap do |b|
242
+ b.use ConfigValidate
243
+ b.use ConnectOpenstack
244
+ b.use Call, IsState, :not_created do |env, b2|
245
+ if env[:result]
246
+ b2.use Message, I18n.t('vagrant_openstack.not_created')
247
+ else
248
+ b2.use SnapshotDelete
249
+ end
250
+ end
251
+ end
252
+ end
253
+
254
+ def self.action_snapshot_list
255
+ new_builder.tap do |b|
256
+ b.use ConfigValidate
257
+ b.use ConnectOpenstack
258
+ b.use Call, IsState, :not_created do |env, b2|
259
+ if env[:result]
260
+ b2.use Message, I18n.t('vagrant_openstack.not_created')
261
+ else
262
+ b2.use SnapshotList
263
+ end
264
+ end
265
+ end
266
+ end
267
+
268
+ def self.action_snapshot_restore
269
+ new_builder.tap do |b|
270
+ b.use ConfigValidate
271
+ b.use ConnectOpenstack
272
+ b.use Call, IsState, :not_created do |env, b2|
273
+ if env[:result]
274
+ b2.use Message, I18n.t('vagrant_openstack.not_created')
275
+ next
276
+ end
277
+
278
+ b2.use SnapshotRestore
279
+ b2.use WaitForServerToBeActive
280
+ b2.use WaitForCommunicator
281
+
282
+ b2.use Call, IsEnvSet, :snapshot_delete do |env2, b3|
283
+ # Used by vagrant push/pop
284
+ b3.use action_snapshot_delete if env2[:result]
285
+ end
286
+
287
+ b2.use action_provision
288
+ end
289
+ end
290
+ end
291
+
292
+ def self.action_snapshot_save
293
+ new_builder.tap do |b|
294
+ b.use ConfigValidate
295
+ b.use ConnectOpenstack
296
+ b.use Call, IsState, :not_created do |env, b2|
297
+ if env[:result]
298
+ b2.use Message, I18n.t('vagrant_openstack.not_created')
299
+ else
300
+ b2.use SnapshotSave
301
+ end
302
+ end
303
+ end
304
+ end
305
+ end # Vagrant > 1.8.0 guard
306
+ # rubocop:enable IndentationWidth
307
+
236
308
  # The autoload farm
237
309
  action_root = Pathname.new(File.expand_path('../action', __FILE__))
238
310
  autoload :Message, action_root.join('message')
@@ -251,6 +323,16 @@ module VagrantPlugins
251
323
  autoload :ProvisionWrapper, action_root.join('provision')
252
324
  autoload :WaitForServerToStop, action_root.join('wait_stop')
253
325
  autoload :WaitForServerToBeActive, action_root.join('wait_active')
326
+ # TODO: Remove the if guard when Vagrant 1.8.0 is the minimum version.
327
+ # rubocop:disable IndentationWidth
328
+ if Gem::Version.new(Vagrant::VERSION) >= Gem::Version.new('1.8.0')
329
+ autoload :SnapshotCleanup, action_root.join('snapshot_cleanup')
330
+ autoload :SnapshotDelete, action_root.join('snapshot_delete')
331
+ autoload :SnapshotList, action_root.join('snapshot_list')
332
+ autoload :SnapshotRestore, action_root.join('snapshot_restore')
333
+ autoload :SnapshotSave, action_root.join('snapshot_save')
334
+ end
335
+ # rubocop:enable IndentationWidth
254
336
 
255
337
  private
256
338
 
@@ -72,7 +72,7 @@ module VagrantPlugins
72
72
  env[:ui].info(" -- ImageRef : #{options[:image].id}")
73
73
  end
74
74
  env[:ui].info(" -- Boot volume : #{options[:volume_boot][:id]} (#{options[:volume_boot][:device]})") unless options[:volume_boot].nil?
75
- env[:ui].info(" -- KeyPair : #{options[:keypair_name]}")
75
+ env[:ui].info(" -- KeyPair : #{options[:keypair_name]}") unless options[:keypair_name].nil?
76
76
 
77
77
  unless options[:networks].empty?
78
78
  formated_networks = ' -- '
@@ -104,7 +104,9 @@ module VagrantPlugins
104
104
  unless options[:image].nil?
105
105
  log << "image '#{options[:image].name}' (#{options[:image].id}) "
106
106
  end
107
- log << "and keypair '#{options[:keypair_name]}'"
107
+ unless options[:keypair_name].nil?
108
+ log << "and keypair '#{options[:keypair_name]}'"
109
+ end
108
110
 
109
111
  @logger.info(log)
110
112
 
@@ -143,6 +145,32 @@ module VagrantPlugins
143
145
  end
144
146
  end
145
147
 
148
+ def assign_floating_ip(env, server_id)
149
+ floating_ip = @resolver.resolve_floating_ip(env)
150
+ return if !floating_ip || floating_ip.empty?
151
+ @logger.info "Using floating IP #{floating_ip}"
152
+ env[:ui].info(I18n.t('vagrant_openstack.using_floating_ip', floating_ip: floating_ip))
153
+ env[:openstack_client].nova.add_floating_ip(env, server_id, floating_ip)
154
+ rescue Errors::UnableToResolveFloatingIP
155
+ @logger.info 'Vagrant was unable to resolve FloatingIP, continue assuming it is not necessary'
156
+ end
157
+
158
+ def waiting_for_floating_ip_to_be_assigned(env, server_id, retry_interval = 3)
159
+ floating_ip = @resolver.resolve_floating_ip(env)
160
+ return if !floating_ip || floating_ip.empty?
161
+ @logger.info "Waiting for floating IP #{floating_ip} to be assigned"
162
+ env[:ui].info(I18n.t('vagrant_openstack.waiting_for_floating_ip', floating_ip: floating_ip))
163
+ config = env[:machine].provider_config
164
+ Timeout.timeout(config.floating_ip_assign_timeout, Errors::Timeout) do
165
+ until env[:openstack_client].nova.check_assigned_floating_ip(env, server_id, floating_ip)
166
+ sleep retry_interval
167
+ end
168
+ return
169
+ end
170
+ rescue Errors::UnableToResolveFloatingIP
171
+ @logger.info 'Vagrant was unable to resolve FloatingIP, not waiting for assignment'
172
+ end
173
+
146
174
  def attach_volumes(env, server_id, volumes)
147
175
  @logger.info("Attaching volumes #{volumes} to server #{server_id}")
148
176
  volumes.each do |volume|
@@ -40,7 +40,9 @@ module VagrantPlugins
40
40
  port: @resolver.resolve_ssh_port(env),
41
41
  username: @resolver.resolve_ssh_username(env)
42
42
  }
43
- hash[:private_key_path] = "#{env[:machine].data_dir}/#{get_keypair_name(env)}" unless config.keypair_name || config.public_key_path
43
+ if env[:machine].config.ssh.insert_key
44
+ hash[:private_key_path] = "#{env[:machine].data_dir}/#{get_keypair_name(env)}" unless config.keypair_name || config.public_key_path
45
+ end
44
46
  # Should work silently when https://github.com/mitchellh/vagrant/issues/4637 is fixed
45
47
  hash[:log_level] = 'ERROR'
46
48
  hash
@@ -0,0 +1,32 @@
1
+ require 'vagrant-conoha/action/abstract_action'
2
+
3
+ module VagrantPlugins
4
+ module ConoHa
5
+ module Action
6
+ class SnapshotCleanup < AbstractAction
7
+ def initialize(app, _env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ nova = env[:openstack_client].nova
13
+ machine_snapshots = nova.list_snapshots(env, env[:machine].id)
14
+
15
+ snapshots_to_clean = machine_snapshots.select do |s|
16
+ s.metadata.key?('vagrant_snapshot')
17
+ end
18
+
19
+ @app.call env
20
+
21
+ unless snapshots_to_clean.empty?
22
+ env[:ui].info("Deleting Vagrant snapshots: #{snapshots_to_clean.map(&:name)}")
23
+ end
24
+
25
+ snapshots_to_clean.each do |s|
26
+ nova.delete_snapshot(env, s.id)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ require 'vagrant-conoha/action/abstract_action'
2
+
3
+ module VagrantPlugins
4
+ module ConoHa
5
+ module Action
6
+ class SnapshotDelete < AbstractAction
7
+ def initialize(app, _env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ nova = env[:openstack_client].nova
13
+ machine_snapshots = nova.list_snapshots(env, env[:machine].id)
14
+
15
+ snapshot = machine_snapshots.find { |s| s.name == env[:snapshot_name] }
16
+
17
+ unless snapshot.nil?
18
+ env[:ui].info(I18n.t('vagrant.actions.vm.snapshot.deleting',
19
+ name: snapshot.name))
20
+
21
+ nova.delete_snapshot(env, snapshot.id)
22
+
23
+ env[:ui].info(I18n.t('vagrant.actions.vm.snapshot.deleted',
24
+ name: snapshot.name))
25
+ end
26
+
27
+ @app.call env
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ require 'vagrant-conoha/action/abstract_action'
2
+
3
+ module VagrantPlugins
4
+ module ConoHa
5
+ module Action
6
+ class SnapshotList < AbstractAction
7
+ def initialize(app, _env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ nova = env[:openstack_client].nova
13
+ machine_snapshots = nova.list_snapshots(env, env[:machine].id)
14
+
15
+ env[:machine_snapshot_list] = machine_snapshots.map(&:name)
16
+
17
+ @app.call env
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ require 'vagrant-conoha/action/abstract_action'
2
+
3
+ module VagrantPlugins
4
+ module ConoHa
5
+ module Action
6
+ class SnapshotRestore < AbstractAction
7
+ def initialize(app, _env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ nova = env[:openstack_client].nova
13
+ machine_snapshots = nova.list_snapshots(env, env[:machine].id)
14
+
15
+ snapshot = machine_snapshots.find { |s| s.name == env[:snapshot_name] }
16
+
17
+ unless snapshot.nil?
18
+ env[:ui].info(I18n.t('vagrant.actions.vm.snapshot.restoring',
19
+ name: snapshot.name))
20
+
21
+ nova.restore_snapshot(env, env[:machine].id, snapshot.id)
22
+ end
23
+
24
+ @app.call env
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,51 @@
1
+ require 'vagrant-conoha/action/abstract_action'
2
+
3
+ module VagrantPlugins
4
+ module ConoHa
5
+ module Action
6
+ class SnapshotSave < AbstractAction
7
+ def initialize(app, _env, retry_interval = 3)
8
+ @app = app
9
+ @retry_interval = retry_interval
10
+ end
11
+
12
+ def call(env)
13
+ nova = env[:openstack_client].nova
14
+ config = env[:machine].provider_config
15
+
16
+ env[:ui].info(I18n.t('vagrant.actions.vm.snapshot.saving',
17
+ name: env[:snapshot_name]))
18
+
19
+ nova.create_snapshot(
20
+ env,
21
+ env[:machine].id, env[:snapshot_name])
22
+
23
+ image = nova.list_snapshots(env, env[:machine].id).find { |i| i.name == env[:snapshot_name] }
24
+
25
+ timeout(config.server_create_timeout, Errors::Timeout) do
26
+ loop do
27
+ image_status = nova.get_image_details(env, image.id)
28
+
29
+ break if image_status['status'] == 'ACTIVE'
30
+
31
+ unless image_status['progress'].nil?
32
+ env[:ui].clear_line
33
+ env[:ui].report_progress(image_status['progress'], 100, false)
34
+ end
35
+
36
+ sleep @retry_interval
37
+ end
38
+ end
39
+
40
+ # Clear progress output.
41
+ env[:ui].clear_line
42
+
43
+ env[:ui].success(I18n.t('vagrant.actions.vm.snapshot.saved',
44
+ name: env[:snapshot_name]))
45
+
46
+ @app.call env
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -56,8 +56,6 @@ module VagrantPlugins
56
56
  config = env[:machine].provider_config
57
57
  rsync_includes = config.rsync_includes.to_a
58
58
 
59
- confirm_rsync_installed(env)
60
-
61
59
  env[:machine].config.vm.synced_folders.each do |_, data|
62
60
  hostpath = File.expand_path(data[:hostpath], env[:root_path])
63
61
  guestpath = data[:guestpath]
@@ -123,22 +121,6 @@ module VagrantPlugins
123
121
 
124
122
  private
125
123
 
126
- def confirm_rsync_installed(env)
127
- # Install rsync if not installed
128
- exit_code = env[:machine].communicate.sudo('which rsync', error_check: false)
129
- return if exit_code == 0 || exit_code.nil?
130
-
131
- config = env[:machine].provider_config
132
-
133
- if config.image =~ /debian|ubuntu/
134
- env[:ui].detail(I18n.t('vagrant_openstack.confirm_rsync_installed'))
135
- env[:machine].communicate.sudo('apt-get update && apt-get install -y rsync')
136
- elsif config.image =~ /centos/
137
- env[:ui].detail(I18n.t('vagrant_openstack.confirm_rsync_installed'))
138
- env[:machine].communicate.sudo('yum -y install rsync')
139
- end
140
- end
141
-
142
124
  def ssh_key_options(ssh_info)
143
125
  # Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
144
126
  Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
@@ -0,0 +1,15 @@
1
+ module VagrantPlugins
2
+ module ConoHa
3
+ module Cap
4
+ module SnapshotList
5
+ # Returns a list of the snapshots that are taken on this machine.
6
+ #
7
+ # @return [Array<String>]
8
+ def self.snapshot_list(machine)
9
+ env = machine.action(:snapshot_list, lock: false)
10
+ env[:machine_snapshot_list]
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -25,19 +25,23 @@ module VagrantPlugins
25
25
  attr_accessor :size
26
26
  attr_accessor :min_ram
27
27
  attr_accessor :min_disk
28
+ attr_accessor :metadata
28
29
 
29
- def initialize(id, name, visibility = nil, size = nil, min_ram = nil, min_disk = nil)
30
+ # rubocop:disable Metrics/ParameterLists
31
+ def initialize(id, name, visibility = nil, size = nil, min_ram = nil, min_disk = nil, metadata = {})
30
32
  @visibility = visibility
31
33
  @size = size
32
34
  @min_ram = min_ram
33
35
  @min_disk = min_disk
36
+ @metadata = metadata
34
37
  super(id, name)
35
38
  end
39
+ # rubocop:enable Metrics/ParameterLists
36
40
 
37
41
  protected
38
42
 
39
43
  def state
40
- [@id, @name, @visibility, @size, @min_ram, @min_disk]
44
+ [@id, @name, @visibility, @size, @min_ram, @min_disk, @metadata]
41
45
  end
42
46
  end
43
47
 
@@ -42,9 +42,30 @@ module VagrantPlugins
42
42
  FloatingIP.new(floating_ip['ip'], floating_ip['pool'], floating_ip['instance_id'])
43
43
  end
44
44
 
45
- def get_all_images(env)
46
- images_json = get(env, "#{@session.endpoints[:compute]}/images")
47
- JSON.parse(images_json)['images'].map { |fl| Image.new(fl['id'], fl['name'], 'unknown') }
45
+ def get_all_images(env, headers = {})
46
+ images_json = get(env, "#{@session.endpoints[:compute]}/images/detail", headers)
47
+ JSON.parse(images_json)['images'].map do |fl|
48
+ Image.new(
49
+ fl['id'],
50
+ fl['name'],
51
+ 'unknown',
52
+ nil,
53
+ fl['minRam'],
54
+ fl['minDisk'],
55
+ fl['metadata']
56
+ )
57
+ end
58
+ end
59
+
60
+ # Get detailed information about an image
61
+ #
62
+ # @param env [Hash] Vagrant action environment
63
+ # @param image_id [String] Image UUID
64
+ #
65
+ # @return [Hash]
66
+ def get_image_details(env, image_id)
67
+ image_json = get(env, "#{@session.endpoints[:compute]}/images/#{image_id}")
68
+ JSON.parse(image_json)['image']
48
69
  end
49
70
 
50
71
  def create_server(env, options)
@@ -70,7 +91,7 @@ module VagrantPlugins
70
91
  s['adminPass'] = options[:admin_pass] unless options[:admin_pass].nil? || options[:admin_pass].empty?
71
92
  s['availability_zone'] = options[:availability_zone] unless options[:availability_zone].nil?
72
93
  s['security_groups'] = options[:security_groups] unless options[:security_groups].nil?
73
- s['user_data'] = Base64.encode64(options[:user_data]) unless options[:user_data].nil?
94
+ s['user_data'] = Base64.strict_encode64(options[:user_data]) unless options[:user_data].nil?
74
95
  s['metadata'] = options[:metadata] unless options[:metadata].nil?
75
96
  s['networks'] = options[:networks] unless options[:networks].nil? || options[:networks].empty?
76
97
  end
@@ -126,6 +147,19 @@ module VagrantPlugins
126
147
  end
127
148
  end
128
149
 
150
+ def check_assigned_floating_ip(env, server_id, floating_ip)
151
+ instance_exists do
152
+ addresses = get_server_details(env, server_id)['addresses']
153
+ addresses.each do |_, network|
154
+ network.each do |network_detail|
155
+ return true if network_detail['addr'] == floating_ip
156
+ end
157
+ end
158
+
159
+ return false
160
+ end
161
+ end
162
+
129
163
  def import_keypair(env, public_key)
130
164
  keyname = "vagrant-generated-#{Kernel.rand(36**8).to_s(36)}"
131
165
 
@@ -177,6 +211,63 @@ module VagrantPlugins
177
211
  end
178
212
  end
179
213
 
214
+ # List snapshot images associated with a particular server
215
+ #
216
+ # @param env [Hash] Vagrant action environment
217
+ # @param server_id [String] Server UUID
218
+ #
219
+ # @return [Array<VagrantPlugins::Openstack::Domain::Image>]
220
+ def list_snapshots(env, server_id)
221
+ get_all_images(env, params: { server: server_id })
222
+ end
223
+
224
+ # Create a named snapsot for a given VM
225
+ #
226
+ # @param env [Hash] Vagrant action environment
227
+ # @param server_id [String] Server UUID
228
+ # @param snapshot_name [String]
229
+ #
230
+ # @return [void]
231
+ def create_snapshot(env, server_id, snapshot_name)
232
+ instance_exists do
233
+ post(
234
+ env,
235
+ "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
236
+ { createImage: {
237
+ name: snapshot_name,
238
+ metadata: { vagrant_snapshot: 'true' }
239
+ } }.to_json)
240
+ end
241
+ end
242
+
243
+ # Delete an identified snapshot
244
+ #
245
+ # @param env [Hash] Vagrant action environment
246
+ # @param snapshot_id [String] Snapshot UUID
247
+ #
248
+ # @return [void]
249
+ def delete_snapshot(env, snapshot_id)
250
+ delete(
251
+ env,
252
+ "#{@session.endpoints[:compute]}/images/#{snapshot_id}")
253
+ end
254
+
255
+ # Restore a VM to an identified snapshot
256
+ #
257
+ # @param env [Hash] Vagrant action environment
258
+ # @param server_id [String] Server UUID
259
+ # @param snapshot_id [String] Snapshot UUID
260
+ #
261
+ # @return [void]
262
+ def restore_snapshot(env, server_id, snapshot_id)
263
+ instance_exists do
264
+ post(
265
+ env,
266
+ "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
267
+ { rebuild: { imageRef: snapshot_id } }.to_json)
268
+ end
269
+ end
270
+
180
271
  private
181
272
 
182
273
  VM_STATES =
@@ -6,19 +6,22 @@ module VagrantPlugins
6
6
  def self.get(env, url, headers = {}, &block)
7
7
  config = env[:machine].provider_config
8
8
  RestClient::Request.execute(method: :get, url: url, headers: headers,
9
- timeout: config.http.read_timeout, open_timeout: config.http.open_timeout, &block)
9
+ timeout: config.http.read_timeout, open_timeout: config.http.open_timeout,
10
+ ssl_ca_file: config.ssl_ca_file, verify_ssl: config.ssl_verify_peer, &block)
10
11
  end
11
12
 
12
13
  def self.post(env, url, payload, headers = {}, &block)
13
14
  config = env[:machine].provider_config
14
15
  RestClient::Request.execute(method: :post, url: url, payload: payload, headers: headers,
15
- timeout: config.http.read_timeout, open_timeout: config.http.open_timeout, &block)
16
+ timeout: config.http.read_timeout, open_timeout: config.http.open_timeout,
17
+ ssl_ca_file: config.ssl_ca_file, verify_ssl: config.ssl_verify_peer, &block)
16
18
  end
17
19
 
18
20
  def self.delete(env, url, headers = {}, &block)
19
21
  config = env[:machine].provider_config
20
22
  RestClient::Request.execute(method: :delete, url: url, headers: headers,
21
- timeout: config.http.read_timeout, open_timeout: config.http.open_timeout, &block)
23
+ timeout: config.http.read_timeout, open_timeout: config.http.open_timeout,
24
+ ssl_ca_file: config.ssl_ca_file, verify_ssl: config.ssl_verify_peer, &block)
22
25
  end
23
26
  end
24
27
  end
@@ -222,6 +222,10 @@ module VagrantPlugins
222
222
  # @return [Integer]
223
223
  attr_accessor :stack_delete_timeout
224
224
 
225
+ #
226
+ # @return [Integer]
227
+ attr_accessor :floating_ip_assign_timeout
228
+
225
229
  #
226
230
  # @return [HttpConfig]
227
231
  attr_accessor :http
@@ -244,6 +248,16 @@ module VagrantPlugins
244
248
  # @return [Boolean]
245
249
  attr_accessor :use_legacy_synced_folders
246
250
 
251
+ # Specify the certificate to use.
252
+ #
253
+ # @return [String]
254
+ attr_accessor :ssl_ca_file
255
+
256
+ # Verify ssl peer certificate when connecting. Set to false (! unsecure) to disable
257
+ #
258
+ # @return [Boolean]
259
+ attr_accessor :ssl_verify_peer
260
+
247
261
  def initialize
248
262
  @password = UNSET_VALUE
249
263
  @openstack_compute_url = UNSET_VALUE
@@ -288,9 +302,12 @@ module VagrantPlugins
288
302
  @server_delete_timeout = UNSET_VALUE
289
303
  @stack_create_timeout = UNSET_VALUE
290
304
  @stack_delete_timeout = UNSET_VALUE
305
+ @floating_ip_assign_timeout = UNSET_VALUE
291
306
  @meta_args_support = UNSET_VALUE
292
307
  @http = HttpConfig.new
293
308
  @use_legacy_synced_folders = UNSET_VALUE
309
+ @ssl_ca_file = UNSET_VALUE
310
+ @ssl_verify_peer = UNSET_VALUE
294
311
  end
295
312
 
296
313
  def merge(other)
@@ -397,11 +414,14 @@ module VagrantPlugins
397
414
  @server_delete_timeout = 200 if @server_delete_timeout == UNSET_VALUE
398
415
  @stack_create_timeout = 200 if @stack_create_timeout == UNSET_VALUE
399
416
  @stack_delete_timeout = 200 if @stack_delete_timeout == UNSET_VALUE
417
+ @floating_ip_assign_timeout = 200 if @floating_ip_assign_timeout == UNSET_VALUE
400
418
  @meta_args_support = false if @meta_args_support == UNSET_VALUE
401
419
  @networks = nil if @networks.empty?
402
420
  @volumes = nil if @volumes.empty?
403
421
  @stacks = nil if @stacks.empty?
404
422
  @http.finalize!
423
+ @ssl_ca_file = nil if @ssl_ca_file == UNSET_VALUE
424
+ @ssl_verify_peer = true if @ssl_verify_peer == UNSET_VALUE
405
425
  end
406
426
  # rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
407
427
 
@@ -423,10 +443,12 @@ module VagrantPlugins
423
443
  validate_stack_config(errors)
424
444
  validate_ssh_timeout(errors)
425
445
 
426
- if machine.config.ssh.private_key_path
427
- puts I18n.t('vagrant_openstack.config.keypair_name_required').yellow unless @keypair_name || @public_key_path
428
- else
429
- errors << I18n.t('vagrant_openstack.config.private_key_missing') if @keypair_name || @public_key_path
446
+ if machine.config.ssh.insert_key
447
+ if machine.config.ssh.private_key_path
448
+ puts I18n.t('vagrant_openstack.config.keypair_name_required').yellow unless @keypair_name || @public_key_path
449
+ else
450
+ errors << I18n.t('vagrant_openstack.config.private_key_missing') if @keypair_name || @public_key_path
451
+ end
430
452
  end
431
453
 
432
454
  {
@@ -33,9 +33,29 @@ module VagrantPlugins
33
33
  resolve_image_internal(env, env[:machine].provider_config.volume_boot[:image])
34
34
  end
35
35
 
36
+ def resolve_floating_ip(env)
37
+ config = env[:machine].provider_config
38
+ nova = env[:openstack_client].nova
39
+ return config.floating_ip if config.floating_ip
40
+
41
+ fail Errors::UnableToResolveFloatingIP if config.floating_ip_pool.nil? || config.floating_ip_pool.empty?
42
+
43
+ @logger.debug 'Searching for available ips'
44
+ free_ip = search_free_ip(config, nova, env)
45
+ config.floating_ip = free_ip
46
+ return free_ip unless free_ip.nil?
47
+
48
+ @logger.debug 'Allocate new ip anyway'
49
+ allocated_ip = allocate_ip(config, nova, env)
50
+ config.floating_ip = allocated_ip
51
+ return allocated_ip unless allocated_ip.nil?
52
+ end
53
+
36
54
  def resolve_keypair(env)
37
55
  config = env[:machine].provider_config
56
+ machine_config = env[:machine].config
38
57
  nova = env[:openstack_client].nova
58
+ return nil unless machine_config.ssh.insert_key
39
59
  return config.keypair_name if config.keypair_name
40
60
  return nova.import_keypair_from_file(env, config.public_key_path) if config.public_key_path
41
61
  generate_keypair(env)
@@ -4,7 +4,7 @@ module VagrantPlugins
4
4
  # Stable versions must respect the pattern given
5
5
  # by VagrantPlugins::ConoHa::VERSION_PATTERN
6
6
  #
7
- VERSION = '0.1.7'
7
+ VERSION = '0.1.8'
8
8
 
9
9
  #
10
10
  # Stable version must respect the naming convention 'x.y.z'
@@ -71,6 +71,8 @@ en:
71
71
  Installing rsync...
72
72
  using_floating_ip: |-
73
73
  Using floating IP %{floating_ip}
74
+ waiting_for_floating_ip: |-
75
+ Waiting for floating IP %{floating_ip} to be assigned...
74
76
  waiting_for_build: |-
75
77
  Waiting for the server to be built...
76
78
  waiting_for_ssh: |-
@@ -108,10 +108,10 @@ describe VagrantPlugins::ConoHa::Action::CreateServer do
108
108
  allow(@action).to receive(:waiting_for_server_to_be_built)
109
109
  allow(@action).to receive(:attach_volumes)
110
110
  allow(@action).to receive(:waiting_for_server_to_be_reachable)
111
+ allow(@action).to receive(:waiting_for_floating_ip_to_be_assigned)
111
112
 
112
113
  expect(@action).to receive(:waiting_for_server_to_be_built).with(env, '45678')
113
114
  expect(@action).to receive(:attach_volumes).with(env, '45678', [{ id: 'vol-01', device: nil }])
114
-
115
115
  @action.call(env)
116
116
  end
117
117
  end
@@ -42,6 +42,7 @@ describe VagrantPlugins::ConoHa::Action::ReadSSHInfo do
42
42
  double('ssh_config').tap do |config|
43
43
  config.stub(:username) { 'sshuser' }
44
44
  config.stub(:port) { nil }
45
+ config.stub(:insert_key) { true }
45
46
  end
46
47
  end
47
48
 
@@ -165,6 +166,16 @@ describe VagrantPlugins::ConoHa::Action::ReadSSHInfo do
165
166
  log_level: 'ERROR')
166
167
  end
167
168
  end
169
+
170
+ context 'with neither keypair_name nor public_key_path specified and ssh.insert_key is false' do
171
+ it 'does not return private_key_path' do
172
+ ssh_config.stub(:insert_key) { false }
173
+ config.stub(:floating_ip) { '80.80.80.80' }
174
+ config.stub(:keypair_name) { nil }
175
+ config.stub(:public_key_path) { nil }
176
+ @action.read_ssh_info(env).should eq(host: '80.80.80.80', port: 22, username: 'sshuser', log_level: 'ERROR')
177
+ end
178
+ end
168
179
  end
169
180
 
170
181
  context 'without config.floating_ip specified' do
@@ -11,6 +11,8 @@ describe VagrantPlugins::ConoHa::CinderClient do
11
11
  let(:config) do
12
12
  double('config').tap do |config|
13
13
  config.stub(:http) { http }
14
+ config.stub(:ssl_ca_file) { nil }
15
+ config.stub(:ssl_verify_peer) { true }
14
16
  end
15
17
  end
16
18
 
@@ -11,6 +11,8 @@ describe VagrantPlugins::ConoHa::GlanceClient do
11
11
  let(:config) do
12
12
  double('config').tap do |config|
13
13
  config.stub(:http) { http }
14
+ config.stub(:ssl_ca_file) { nil }
15
+ config.stub(:ssl_verify_peer) { true }
14
16
  end
15
17
  end
16
18
 
@@ -18,6 +18,8 @@ describe VagrantPlugins::ConoHa::NovaClient do
18
18
  config.stub(:username) { 'username' }
19
19
  config.stub(:password) { 'password' }
20
20
  config.stub(:http) { http }
21
+ config.stub(:ssl_ca_file) { nil }
22
+ config.stub(:ssl_verify_peer) { true }
21
23
  end
22
24
  end
23
25
 
@@ -20,6 +20,8 @@ describe VagrantPlugins::ConoHa::KeystoneClient do
20
20
  config.stub(:interface_type) { 'public' }
21
21
  config.stub(:identity_api_version) { '2' }
22
22
  config.stub(:project_name) { 'testTenant' }
23
+ config.stub(:ssl_ca_file) { nil }
24
+ config.stub(:ssl_verify_peer) { true }
23
25
  end
24
26
  end
25
27
 
@@ -11,6 +11,8 @@ describe VagrantPlugins::ConoHa::NeutronClient do
11
11
  let(:config) do
12
12
  double('config').tap do |config|
13
13
  config.stub(:http) { http }
14
+ config.stub(:ssl_ca_file) { nil }
15
+ config.stub(:ssl_verify_peer) { true }
14
16
  end
15
17
  end
16
18
 
@@ -21,6 +21,8 @@ describe VagrantPlugins::ConoHa::NovaClient do
21
21
  config.stub(:username) { 'username' }
22
22
  config.stub(:password) { 'password' }
23
23
  config.stub(:http) { http }
24
+ config.stub(:ssl_ca_file) { nil }
25
+ config.stub(:ssl_verify_peer) { true }
24
26
  end
25
27
  end
26
28
 
@@ -101,7 +103,7 @@ describe VagrantPlugins::ConoHa::NovaClient do
101
103
  describe 'get_all_images' do
102
104
  context 'with token and project_id acquainted' do
103
105
  it 'returns all images' do
104
- stub_request(:get, 'http://nova/a1b2c3/images')
106
+ stub_request(:get, 'http://nova/a1b2c3/images/detail')
105
107
  .with(
106
108
  headers:
107
109
  {
@@ -110,13 +112,14 @@ describe VagrantPlugins::ConoHa::NovaClient do
110
112
  })
111
113
  .to_return(
112
114
  status: 200,
113
- body: '{ "images": [ { "id": "i1", "name": "image1"}, { "id": "i2", "name": "image2"} ] }')
115
+ body: '{ "images": [ { "id": "i1", "name": "image1", "metadata": {"customVal1": 1}}, { "id": "i2", "name": "image2"} ] }')
114
116
 
115
117
  images = @nova_client.get_all_images(env)
116
118
 
117
119
  expect(images.length).to eq(2)
118
120
  expect(images[0].id).to eq('i1')
119
121
  expect(images[0].name).to eq('image1')
122
+ expect(images[0].metadata['customVal1']).to eq(1)
120
123
  expect(images[1].id).to eq('i2')
121
124
  expect(images[1].name).to eq('image2')
122
125
  end
@@ -147,7 +150,7 @@ describe VagrantPlugins::ConoHa::NovaClient do
147
150
  stub_request(:post, 'http://nova/a1b2c3/servers')
148
151
  .with(
149
152
  body: '{"server":{"name":"inst","imageRef":"img","flavorRef":"flav","key_name":"key","adminPass":"AdminPass123%",'\
150
- '"security_groups":[{"name":"default"}],"user_data":"dXNlcl9kYXRhX3Rlc3Q=\n","metadata":"metadata_test"},'\
153
+ '"security_groups":[{"name":"default"}],"user_data":"dXNlcl9kYXRhX3Rlc3Q=","metadata":"metadata_test"},'\
151
154
  '"os:scheduler_hints":"sched_hints_test"}',
152
155
  headers:
153
156
  {
@@ -93,6 +93,7 @@ describe VagrantPlugins::ConoHa::ConfigResolver do
93
93
  double('ssh_config').tap do |config|
94
94
  config.stub(:username) { nil }
95
95
  config.stub(:port) { nil }
96
+ config.stub(:insert_key) { true }
96
97
  end
97
98
  end
98
99
 
@@ -397,6 +398,16 @@ describe VagrantPlugins::ConoHa::ConfigResolver do
397
398
  @action.resolve_keypair(env).should eq('my-keypair-imported')
398
399
  end
399
400
  end
401
+
402
+ context 'with insert_key false' do
403
+ it 'does nothing and return nil' do
404
+ config.stub(:keypair_name) { 'my-keypair' }
405
+ ssh_config.stub(:insert_key) { false }
406
+ nova.should_not_receive(:import_keypair_from_file)
407
+ @action.should_not_receive(:generate_keypair)
408
+ @action.resolve_keypair(env).should be_nil
409
+ end
410
+ end
400
411
  end
401
412
 
402
413
  describe 'generate_keypair' do
@@ -29,6 +29,7 @@ describe VagrantPlugins::ConoHa::Config do
29
29
  its(:security_groups) { should be_nil }
30
30
  its(:user_data) { should be_nil }
31
31
  its(:metadata) { should be_nil }
32
+ its(:ssl_ca_file) { should eq nil }
32
33
  end
33
34
 
34
35
  describe 'overriding defaults' do
@@ -50,7 +51,8 @@ describe VagrantPlugins::ConoHa::Config do
50
51
  :user_data,
51
52
  :metadata,
52
53
  :availability_zone,
53
- :public_key_path].each do |attribute|
54
+ :public_key_path,
55
+ :ssl_ca_file].each do |attribute|
54
56
  it "should not default #{attribute} if overridden" do
55
57
  subject.send("#{attribute}=".to_sym, 'foo')
56
58
  subject.finalize!
@@ -270,6 +272,7 @@ describe VagrantPlugins::ConoHa::Config do
270
272
  machine.stub_chain(:env, :root_path).and_return '/'
271
273
  ssh.stub(:private_key_path) { 'private key path' }
272
274
  ssh.stub(:username) { 'ssh username' }
275
+ ssh.stub(:insert_key) { true }
273
276
  config.stub(:ssh) { ssh }
274
277
  machine.stub(:config) { config }
275
278
  subject.username = 'foo'
@@ -348,6 +351,16 @@ describe VagrantPlugins::ConoHa::Config do
348
351
  validation_errors.first.should == error_message
349
352
  end
350
353
  end
354
+
355
+ context 'keypair_name or public_key_path is set and ssh.insert_key is false' do
356
+ it 'should not error' do
357
+ ssh.stub(:private_key_path) { nil }
358
+ ssh.stub(:insert_key) { false }
359
+ subject.public_key_path = 'public_key'
360
+ I18n.should_not_receive(:t)
361
+ validation_errors.should be_empty
362
+ end
363
+ end
351
364
  end
352
365
 
353
366
  context 'the password' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-conoha
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hironobu Saitoh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-24 00:00:00.000000000 Z
11
+ date: 2017-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -210,6 +210,11 @@ files:
210
210
  - lib/vagrant-conoha/action/read_ssh_info.rb
211
211
  - lib/vagrant-conoha/action/read_state.rb
212
212
  - lib/vagrant-conoha/action/resume.rb
213
+ - lib/vagrant-conoha/action/snapshot_cleanup.rb
214
+ - lib/vagrant-conoha/action/snapshot_delete.rb
215
+ - lib/vagrant-conoha/action/snapshot_list.rb
216
+ - lib/vagrant-conoha/action/snapshot_restore.rb
217
+ - lib/vagrant-conoha/action/snapshot_save.rb
213
218
  - lib/vagrant-conoha/action/start_server.rb
214
219
  - lib/vagrant-conoha/action/stop_server.rb
215
220
  - lib/vagrant-conoha/action/suspend.rb
@@ -217,6 +222,7 @@ files:
217
222
  - lib/vagrant-conoha/action/wait_accessible.rb
218
223
  - lib/vagrant-conoha/action/wait_active.rb
219
224
  - lib/vagrant-conoha/action/wait_stop.rb
225
+ - lib/vagrant-conoha/cap/snapshot_list.rb
220
226
  - lib/vagrant-conoha/catalog/openstack_catalog.rb
221
227
  - lib/vagrant-conoha/client/cinder.rb
222
228
  - lib/vagrant-conoha/client/domain.rb