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.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -1
- data/CHANGELOG.md +3 -0
- data/Vagrantfile +9 -0
- data/lib/vagrant-conoha/action.rb +82 -0
- data/lib/vagrant-conoha/action/create_server.rb +30 -2
- data/lib/vagrant-conoha/action/read_ssh_info.rb +3 -1
- data/lib/vagrant-conoha/action/snapshot_cleanup.rb +32 -0
- data/lib/vagrant-conoha/action/snapshot_delete.rb +32 -0
- data/lib/vagrant-conoha/action/snapshot_list.rb +22 -0
- data/lib/vagrant-conoha/action/snapshot_restore.rb +29 -0
- data/lib/vagrant-conoha/action/snapshot_save.rb +51 -0
- data/lib/vagrant-conoha/action/sync_folders.rb +0 -18
- data/lib/vagrant-conoha/cap/snapshot_list.rb +15 -0
- data/lib/vagrant-conoha/client/domain.rb +6 -2
- data/lib/vagrant-conoha/client/nova.rb +95 -4
- data/lib/vagrant-conoha/client/rest_utils.rb +6 -3
- data/lib/vagrant-conoha/config.rb +26 -4
- data/lib/vagrant-conoha/config_resolver.rb +20 -0
- data/lib/vagrant-conoha/version.rb +1 -1
- data/locales/en.yml +2 -0
- data/spec/vagrant-conoha/action/create_server_spec.rb +1 -1
- data/spec/vagrant-conoha/action/read_ssh_info_spec.rb +11 -0
- data/spec/vagrant-conoha/client/cinder_spec.rb +2 -0
- data/spec/vagrant-conoha/client/glance_spec.rb +2 -0
- data/spec/vagrant-conoha/client/heat_spec.rb +2 -0
- data/spec/vagrant-conoha/client/keystone_spec.rb +2 -0
- data/spec/vagrant-conoha/client/neutron_spec.rb +2 -0
- data/spec/vagrant-conoha/client/nova_spec.rb +6 -3
- data/spec/vagrant-conoha/config_resolver_spec.rb +11 -0
- data/spec/vagrant-conoha/config_spec.rb +14 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c29698b0a2fe6b73bc0c0aa25018eba9983b07c
|
4
|
+
data.tar.gz: 1894ed5c1de790b660ba5a9d7e8d0857528dedaf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 958d00ad314df677595e667229d8a0520f98f4e7d5138118f2d1135e6daeefd9fe7f01954ffb80fd6f1617fceb8615f6c08293895c893f1ef5c3c0893e71ed68
|
7
|
+
data.tar.gz: 786d1afd0eceaff4336b9b4d757140f5cbf165c61acdc105e1a597ef604ae099105ad396b76a57805659a1dccc62bafba15361adeadef2c9952beaa79b35a51f
|
data/.rubocop.yml
CHANGED
@@ -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:
|
28
|
+
Max: 65
|
28
29
|
|
29
30
|
Metrics/LineLength:
|
30
31
|
Max: 150
|
data/CHANGELOG.md
CHANGED
data/Vagrantfile
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
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.
|
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,
|
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,
|
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,
|
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.
|
427
|
-
|
428
|
-
|
429
|
-
|
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)
|
data/locales/en.yml
CHANGED
@@ -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
|
@@ -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
|
|
@@ -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
|
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
|
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.
|
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-
|
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
|