vagrant-conoha 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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