vagrant-conoha 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.rubocop.yml +35 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +19 -0
- data/LICENSE +23 -0
- data/Rakefile +25 -0
- data/Vagrantfile +71 -0
- data/dummy.box +0 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/functional_tests/Vagrantfile +58 -0
- data/functional_tests/keys/vagrant-openstack +27 -0
- data/functional_tests/keys/vagrant-openstack.pub +1 -0
- data/functional_tests/run_tests.sh +142 -0
- data/lib/vagrant-conoha.rb +29 -0
- data/lib/vagrant-conoha/action.rb +227 -0
- data/lib/vagrant-conoha/action/abstract_action.rb +22 -0
- data/lib/vagrant-conoha/action/connect_openstack.rb +60 -0
- data/lib/vagrant-conoha/action/create_server.rb +154 -0
- data/lib/vagrant-conoha/action/create_stack.rb +68 -0
- data/lib/vagrant-conoha/action/delete_server.rb +53 -0
- data/lib/vagrant-conoha/action/delete_stack.rb +73 -0
- data/lib/vagrant-conoha/action/message.rb +19 -0
- data/lib/vagrant-conoha/action/provision.rb +60 -0
- data/lib/vagrant-conoha/action/read_ssh_info.rb +72 -0
- data/lib/vagrant-conoha/action/read_state.rb +43 -0
- data/lib/vagrant-conoha/action/resume.rb +24 -0
- data/lib/vagrant-conoha/action/start_server.rb +24 -0
- data/lib/vagrant-conoha/action/stop_server.rb +25 -0
- data/lib/vagrant-conoha/action/suspend.rb +24 -0
- data/lib/vagrant-conoha/action/sync_folders.rb +129 -0
- data/lib/vagrant-conoha/action/wait_accessible.rb +61 -0
- data/lib/vagrant-conoha/action/wait_active.rb +33 -0
- data/lib/vagrant-conoha/action/wait_stop.rb +33 -0
- data/lib/vagrant-conoha/catalog/openstack_catalog.rb +67 -0
- data/lib/vagrant-conoha/client/cinder.rb +39 -0
- data/lib/vagrant-conoha/client/domain.rb +159 -0
- data/lib/vagrant-conoha/client/glance.rb +65 -0
- data/lib/vagrant-conoha/client/heat.rb +49 -0
- data/lib/vagrant-conoha/client/http_utils.rb +116 -0
- data/lib/vagrant-conoha/client/keystone.rb +77 -0
- data/lib/vagrant-conoha/client/neutron.rb +48 -0
- data/lib/vagrant-conoha/client/nova.rb +212 -0
- data/lib/vagrant-conoha/client/openstack.rb +59 -0
- data/lib/vagrant-conoha/client/request_logger.rb +23 -0
- data/lib/vagrant-conoha/client/rest_utils.rb +25 -0
- data/lib/vagrant-conoha/command/abstract_command.rb +51 -0
- data/lib/vagrant-conoha/command/flavor_list.rb +24 -0
- data/lib/vagrant-conoha/command/image_list.rb +29 -0
- data/lib/vagrant-conoha/command/main.rb +51 -0
- data/lib/vagrant-conoha/command/network_list.rb +25 -0
- data/lib/vagrant-conoha/command/openstack_command.rb +16 -0
- data/lib/vagrant-conoha/command/reset.rb +20 -0
- data/lib/vagrant-conoha/command/subnet_list.rb +22 -0
- data/lib/vagrant-conoha/command/utils.rb +22 -0
- data/lib/vagrant-conoha/command/volume_list.rb +25 -0
- data/lib/vagrant-conoha/config.rb +390 -0
- data/lib/vagrant-conoha/config/http.rb +39 -0
- data/lib/vagrant-conoha/config_resolver.rb +285 -0
- data/lib/vagrant-conoha/errors.rb +187 -0
- data/lib/vagrant-conoha/logging.rb +39 -0
- data/lib/vagrant-conoha/plugin.rb +48 -0
- data/lib/vagrant-conoha/provider.rb +50 -0
- data/lib/vagrant-conoha/utils.rb +26 -0
- data/lib/vagrant-conoha/version.rb +15 -0
- data/lib/vagrant-conoha/version_checker.rb +76 -0
- data/locales/en.yml +393 -0
- data/spec/vagrant-conoha/action/connect_openstack_spec.rb +695 -0
- data/spec/vagrant-conoha/action/create_server_spec.rb +225 -0
- data/spec/vagrant-conoha/action/create_stack_spec.rb +99 -0
- data/spec/vagrant-conoha/action/delete_server_spec.rb +89 -0
- data/spec/vagrant-conoha/action/delete_stack_spec.rb +63 -0
- data/spec/vagrant-conoha/action/message_spec.rb +33 -0
- data/spec/vagrant-conoha/action/provision_spec.rb +104 -0
- data/spec/vagrant-conoha/action/read_ssh_info_spec.rb +190 -0
- data/spec/vagrant-conoha/action/read_state_spec.rb +81 -0
- data/spec/vagrant-conoha/action/resume_server_spec.rb +49 -0
- data/spec/vagrant-conoha/action/start_server_spec.rb +49 -0
- data/spec/vagrant-conoha/action/stop_server_spec.rb +49 -0
- data/spec/vagrant-conoha/action/suspend_server_spec.rb +49 -0
- data/spec/vagrant-conoha/action/sync_folders_spec.rb +155 -0
- data/spec/vagrant-conoha/action/wait_accessible_spec.rb +67 -0
- data/spec/vagrant-conoha/action/wait_active_spec.rb +53 -0
- data/spec/vagrant-conoha/action/wait_stop_spec.rb +53 -0
- data/spec/vagrant-conoha/action_spec.rb +120 -0
- data/spec/vagrant-conoha/client/cinder_spec.rb +127 -0
- data/spec/vagrant-conoha/client/glance_spec.rb +143 -0
- data/spec/vagrant-conoha/client/heat_spec.rb +128 -0
- data/spec/vagrant-conoha/client/keystone_spec.rb +150 -0
- data/spec/vagrant-conoha/client/neutron_spec.rb +171 -0
- data/spec/vagrant-conoha/client/nova_spec.rb +757 -0
- data/spec/vagrant-conoha/client/utils_spec.rb +176 -0
- data/spec/vagrant-conoha/command/flavor_list_spec.rb +43 -0
- data/spec/vagrant-conoha/command/image_list_spec.rb +95 -0
- data/spec/vagrant-conoha/command/network_list_spec.rb +65 -0
- data/spec/vagrant-conoha/command/reset_spec.rb +24 -0
- data/spec/vagrant-conoha/command/subnet_list_spec.rb +45 -0
- data/spec/vagrant-conoha/command/volume_list_spec.rb +40 -0
- data/spec/vagrant-conoha/config_resolver_spec.rb +860 -0
- data/spec/vagrant-conoha/config_spec.rb +373 -0
- data/spec/vagrant-conoha/e2e_spec.rb.save +27 -0
- data/spec/vagrant-conoha/provider_spec.rb +13 -0
- data/spec/vagrant-conoha/spec_helper.rb +37 -0
- data/spec/vagrant-conoha/utils_spec.rb +129 -0
- data/spec/vagrant-conoha/version_checker_spec.rb +39 -0
- data/stackrc +25 -0
- data/vagrant-conoha.gemspec +32 -0
- metadata +343 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
require 'vagrant-conoha/client/heat'
|
|
5
|
+
require 'vagrant-conoha/client/keystone'
|
|
6
|
+
require 'vagrant-conoha/client/nova'
|
|
7
|
+
require 'vagrant-conoha/client/neutron'
|
|
8
|
+
require 'vagrant-conoha/client/cinder'
|
|
9
|
+
require 'vagrant-conoha/client/glance'
|
|
10
|
+
|
|
11
|
+
module VagrantPlugins
|
|
12
|
+
module ConoHa
|
|
13
|
+
class Session
|
|
14
|
+
include Singleton
|
|
15
|
+
|
|
16
|
+
attr_accessor :token
|
|
17
|
+
attr_accessor :project_id
|
|
18
|
+
attr_accessor :endpoints
|
|
19
|
+
|
|
20
|
+
def initialize
|
|
21
|
+
@token = nil
|
|
22
|
+
@project_id = nil
|
|
23
|
+
@endpoints = {}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def reset
|
|
27
|
+
initialize
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.session
|
|
32
|
+
Session.instance
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.keystone
|
|
36
|
+
ConoHa::KeystoneClient.instance
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.nova
|
|
40
|
+
ConoHa::NovaClient.instance
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.heat
|
|
44
|
+
ConoHa::HeatClient.instance
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.neutron
|
|
48
|
+
ConoHa::NeutronClient.instance
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.cinder
|
|
52
|
+
ConoHa::CinderClient.instance
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.glance
|
|
56
|
+
ConoHa::GlanceClient.instance
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'log4r'
|
|
2
|
+
require 'json'
|
|
3
|
+
|
|
4
|
+
module VagrantPlugins
|
|
5
|
+
module ConoHa
|
|
6
|
+
module HttpUtils
|
|
7
|
+
module RequestLogger
|
|
8
|
+
def log_request(method, url, body = nil, headers)
|
|
9
|
+
@logger.debug "request => method : #{method}"
|
|
10
|
+
@logger.debug "request => url : #{url}"
|
|
11
|
+
@logger.debug "request => headers : #{headers}"
|
|
12
|
+
@logger.debug "request => body : #{body}" unless body.nil?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def log_response(response)
|
|
16
|
+
@logger.debug "response => code : #{response.code}"
|
|
17
|
+
@logger.debug "response => headers : #{response.headers}"
|
|
18
|
+
@logger.debug "response => body : #{response}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'restclient'
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module ConoHa
|
|
5
|
+
module RestUtils
|
|
6
|
+
def self.get(env, url, headers = {}, &block)
|
|
7
|
+
config = env[:machine].provider_config
|
|
8
|
+
RestClient::Request.execute(method: :get, url: url, headers: headers,
|
|
9
|
+
timeout: config.http.read_timeout, open_timeout: config.http.open_timeout, &block)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.post(env, url, payload, headers = {}, &block)
|
|
13
|
+
config = env[:machine].provider_config
|
|
14
|
+
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
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.delete(env, url, headers = {}, &block)
|
|
19
|
+
config = env[:machine].provider_config
|
|
20
|
+
RestClient::Request.execute(method: :delete, url: url, headers: headers,
|
|
21
|
+
timeout: config.http.read_timeout, open_timeout: config.http.open_timeout, &block)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'vagrant-conoha/client/openstack'
|
|
2
|
+
require 'colorize'
|
|
3
|
+
|
|
4
|
+
module VagrantPlugins
|
|
5
|
+
module ConoHa
|
|
6
|
+
module Command
|
|
7
|
+
class AbstractCommand < Vagrant.plugin('2', :command)
|
|
8
|
+
def initialize(argv, env)
|
|
9
|
+
@env = env
|
|
10
|
+
super(normalize_args(argv), env)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def execute(name)
|
|
14
|
+
env = {}
|
|
15
|
+
with_target_vms(nil, provider: :conoha) do |machine|
|
|
16
|
+
env[:machine] = machine
|
|
17
|
+
env[:ui] = @env.ui
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
before_cmd(name, @argv, env)
|
|
21
|
+
|
|
22
|
+
cmd(name, @argv, env)
|
|
23
|
+
@env.ui.info('')
|
|
24
|
+
# rubocop:disable Lint/RescueException
|
|
25
|
+
rescue Errors::VagrantOpenstackError, SystemExit, Interrupt => e
|
|
26
|
+
raise e
|
|
27
|
+
rescue Exception => e
|
|
28
|
+
puts I18n.t('vagrant_openstack.global_error').red unless e.message && e.message.start_with?('Catched Error:')
|
|
29
|
+
raise e
|
|
30
|
+
end
|
|
31
|
+
# rubocop:enable Lint/RescueException
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# Before Vagrant 1.5, args list ends with an extra arg '--'. It removes it if present.
|
|
35
|
+
#
|
|
36
|
+
def normalize_args(args)
|
|
37
|
+
return args if args.nil?
|
|
38
|
+
args.pop if args.size > 0 && args.last == '--'
|
|
39
|
+
args
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def before_cmd(_name, _argv, _env)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def cmd(_name, _argv, _env)
|
|
46
|
+
fail 'Command not implemented. \'cmd\' method must be overridden in all subclasses'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'vagrant-conoha/command/openstack_command'
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module ConoHa
|
|
5
|
+
module Command
|
|
6
|
+
class FlavorList < OpenstackCommand
|
|
7
|
+
def self.synopsis
|
|
8
|
+
I18n.t('vagrant_openstack.command.flavor_list_synopsis')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def cmd(name, argv, env)
|
|
12
|
+
fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
|
|
13
|
+
flavors = env[:openstack_client].nova.get_all_flavors(env)
|
|
14
|
+
|
|
15
|
+
rows = []
|
|
16
|
+
flavors.each do |f|
|
|
17
|
+
rows << [f.id, f.name, f.vcpus, f.ram, f.disk]
|
|
18
|
+
end
|
|
19
|
+
display_table(env, ['Id', 'Name', 'vCPU', 'RAM (Mo)', 'Disk size (Go)'], rows)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'vagrant-conoha/command/openstack_command'
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module ConoHa
|
|
5
|
+
module Command
|
|
6
|
+
class ImageList < OpenstackCommand
|
|
7
|
+
def self.synopsis
|
|
8
|
+
I18n.t('vagrant_openstack.command.image_list_synopsis')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def cmd(name, argv, env)
|
|
12
|
+
fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
|
|
13
|
+
rows = []
|
|
14
|
+
headers = %w(Id Name)
|
|
15
|
+
if env[:openstack_client].session.endpoints.key? :image
|
|
16
|
+
images = env[:openstack_client].glance.get_all_images(env)
|
|
17
|
+
images.each { |i| rows << [i.id, i.name, i.visibility, i.size.to_i / 1024 / 1024, i.min_ram, i.min_disk] }
|
|
18
|
+
headers << ['Visibility', 'Size (Mo)', 'Min RAM (Go)', 'Min Disk (Go)']
|
|
19
|
+
headers = headers.flatten
|
|
20
|
+
else
|
|
21
|
+
images = env[:openstack_client].nova.get_all_images(env)
|
|
22
|
+
images.each { |image| rows << [image.id, image.name] }
|
|
23
|
+
end
|
|
24
|
+
display_table(env, headers, rows)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module VagrantPlugins
|
|
2
|
+
module ConoHa
|
|
3
|
+
module Command
|
|
4
|
+
COMMANDS = [
|
|
5
|
+
{ name: :'image-list', file: 'image_list', clazz: 'ImageList' },
|
|
6
|
+
{ name: :'flavor-list', file: 'flavor_list', clazz: 'FlavorList' },
|
|
7
|
+
{ name: :'network-list', file: 'network_list', clazz: 'NetworkList' },
|
|
8
|
+
{ name: :'subnet-list', file: 'subnet_list', clazz: 'SubnetList' },
|
|
9
|
+
{ name: :'volume-list', file: 'volume_list', clazz: 'VolumeList' },
|
|
10
|
+
{ name: :'reset', file: 'reset', clazz: 'Reset' }
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
class Main < Vagrant.plugin('2', :command)
|
|
14
|
+
def self.synopsis
|
|
15
|
+
I18n.t('vagrant_openstack.command.main_synopsis')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(argv, env)
|
|
19
|
+
@env = env
|
|
20
|
+
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
|
21
|
+
@commands = Vagrant::Registry.new
|
|
22
|
+
|
|
23
|
+
COMMANDS.each do |cmd|
|
|
24
|
+
@commands.register(cmd[:name]) do
|
|
25
|
+
require_relative cmd[:file]
|
|
26
|
+
Command.const_get(cmd[:clazz])
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
super(argv, env)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def execute
|
|
34
|
+
command_class = @commands.get(@sub_command.to_sym) if @sub_command
|
|
35
|
+
return usage unless command_class && @sub_command
|
|
36
|
+
command_class.new(@sub_args, @env).execute(@sub_command)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def usage
|
|
40
|
+
@env.ui.info I18n.t('vagrant_openstack.command.main_usage')
|
|
41
|
+
@env.ui.info ''
|
|
42
|
+
@env.ui.info I18n.t('vagrant_openstack.command.available_subcommands')
|
|
43
|
+
@commands.each do |key, value|
|
|
44
|
+
@env.ui.info " #{key.to_s.ljust(20)} #{value.synopsis}"
|
|
45
|
+
end
|
|
46
|
+
@env.ui.info ''
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'vagrant-conoha/command/openstack_command'
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module ConoHa
|
|
5
|
+
module Command
|
|
6
|
+
class NetworkList < OpenstackCommand
|
|
7
|
+
def self.synopsis
|
|
8
|
+
I18n.t('vagrant_openstack.command.network_list_synopsis')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def cmd(name, argv, env)
|
|
12
|
+
fail Errors::UnrecognizedArgForCommand, cmd: name, arg: argv[1] if argv.size > 1
|
|
13
|
+
if argv.size == 0
|
|
14
|
+
networks = env[:openstack_client].neutron.get_private_networks(env)
|
|
15
|
+
elsif argv[0] == 'all'
|
|
16
|
+
networks = env[:openstack_client].neutron.get_all_networks(env)
|
|
17
|
+
else
|
|
18
|
+
fail Errors::UnrecognizedArgForCommand, cmd: name, arg: argv[0]
|
|
19
|
+
end
|
|
20
|
+
display_item_list(env, networks)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'vagrant-conoha/command/utils'
|
|
2
|
+
require 'vagrant-conoha/command/abstract_command'
|
|
3
|
+
|
|
4
|
+
module VagrantPlugins
|
|
5
|
+
module ConoHa
|
|
6
|
+
module Command
|
|
7
|
+
class OpenstackCommand < AbstractCommand
|
|
8
|
+
include VagrantPlugins::ConoHa::Command::Utils
|
|
9
|
+
|
|
10
|
+
def before_cmd(_name, _argv, env)
|
|
11
|
+
VagrantPlugins::ConoHa::Action::ConnectOpenstack.new(nil, env).call(env)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'vagrant-conoha/command/utils'
|
|
2
|
+
require 'vagrant-conoha/command/abstract_command'
|
|
3
|
+
|
|
4
|
+
module VagrantPlugins
|
|
5
|
+
module ConoHa
|
|
6
|
+
module Command
|
|
7
|
+
class Reset < AbstractCommand
|
|
8
|
+
def self.synopsis
|
|
9
|
+
I18n.t('vagrant_openstack.command.reset')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def cmd(name, argv, env)
|
|
13
|
+
fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
|
|
14
|
+
FileUtils.remove_dir("#{env[:machine].data_dir}")
|
|
15
|
+
env[:ui].info 'Vagrant ConoHa has been reset.'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'vagrant-conoha/command/openstack_command'
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module ConoHa
|
|
5
|
+
module Command
|
|
6
|
+
class SubnetList < OpenstackCommand
|
|
7
|
+
def self.synopsis
|
|
8
|
+
I18n.t('vagrant_openstack.command.subnet_list_synopsis')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def cmd(name, argv, env)
|
|
12
|
+
fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
|
|
13
|
+
rows = []
|
|
14
|
+
env[:openstack_client].neutron.get_subnets(env).each do |subnet|
|
|
15
|
+
rows << [subnet.id, subnet.name, subnet.cidr, subnet.enable_dhcp, subnet.network_id]
|
|
16
|
+
end
|
|
17
|
+
display_table(env, ['Id', 'Name', 'CIDR', 'DHCP', 'Network Id'], rows)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'terminal-table'
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module ConoHa
|
|
5
|
+
module Command
|
|
6
|
+
module Utils
|
|
7
|
+
def display_item_list(env, items)
|
|
8
|
+
rows = []
|
|
9
|
+
items.each do |item|
|
|
10
|
+
rows << [item.id, item.name]
|
|
11
|
+
end
|
|
12
|
+
display_table(env, %w(Id Name), rows)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def display_table(env, headers, rows)
|
|
16
|
+
table = Terminal::Table.new headings: headers, rows: rows
|
|
17
|
+
env[:ui].info("\n#{table}")
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'vagrant-conoha/command/openstack_command'
|
|
2
|
+
|
|
3
|
+
module VagrantPlugins
|
|
4
|
+
module ConoHa
|
|
5
|
+
module Command
|
|
6
|
+
class VolumeList < OpenstackCommand
|
|
7
|
+
def self.synopsis
|
|
8
|
+
I18n.t('vagrant_openstack.command.volume_list_synopsis')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def cmd(name, argv, env)
|
|
12
|
+
fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 0
|
|
13
|
+
volumes = env[:openstack_client].cinder.get_all_volumes(env)
|
|
14
|
+
|
|
15
|
+
rows = []
|
|
16
|
+
volumes.each do |v|
|
|
17
|
+
attachment = "#{v.instance_id} (#{v.device})" unless v.instance_id.nil?
|
|
18
|
+
rows << [v.id, v.name, v.size, v.status, attachment]
|
|
19
|
+
end
|
|
20
|
+
display_table(env, ['Id', 'Name', 'Size (Go)', 'Status', 'Attachment (instance id and device)'], rows)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
require 'vagrant'
|
|
2
|
+
require 'colorize'
|
|
3
|
+
require 'vagrant-conoha/config/http'
|
|
4
|
+
|
|
5
|
+
module VagrantPlugins
|
|
6
|
+
module ConoHa
|
|
7
|
+
class Config < Vagrant.plugin('2', :config)
|
|
8
|
+
# The API key to access Openstack.
|
|
9
|
+
#
|
|
10
|
+
attr_accessor :password
|
|
11
|
+
|
|
12
|
+
# The compute service url to access Openstack. If nil, it will read from hypermedia catalog form REST API
|
|
13
|
+
#
|
|
14
|
+
attr_accessor :openstack_compute_url
|
|
15
|
+
|
|
16
|
+
# The network service url to access Openstack. If nil, it will read from hypermedia catalog form REST API
|
|
17
|
+
#
|
|
18
|
+
attr_accessor :openstack_network_url
|
|
19
|
+
|
|
20
|
+
# The block storage service url to access Openstack. If nil, it will read from hypermedia catalog form REST API
|
|
21
|
+
#
|
|
22
|
+
attr_accessor :openstack_volume_url
|
|
23
|
+
|
|
24
|
+
# The orchestration service url to access Openstack. If nil, it will read from hypermedia catalog form REST API
|
|
25
|
+
#
|
|
26
|
+
attr_accessor :openstack_orchestration_url
|
|
27
|
+
|
|
28
|
+
# The image service url to access Openstack. If nil, it will read from hypermedia catalog form REST API
|
|
29
|
+
#
|
|
30
|
+
attr_accessor :openstack_image_url
|
|
31
|
+
|
|
32
|
+
# The authentication endpoint. This defaults to Openstack's global authentication endpoint.
|
|
33
|
+
attr_accessor :openstack_auth_url
|
|
34
|
+
|
|
35
|
+
# Openstack region
|
|
36
|
+
attr_accessor :region
|
|
37
|
+
|
|
38
|
+
# The flavor of server to launch, either the ID or name. This
|
|
39
|
+
# can also be a regular expression to partially match a name.
|
|
40
|
+
attr_accessor :flavor
|
|
41
|
+
|
|
42
|
+
# The name or ID of the image to use. This can also be a regular
|
|
43
|
+
# expression to partially match a name.
|
|
44
|
+
attr_accessor :image
|
|
45
|
+
|
|
46
|
+
# Volume to boot the vm from
|
|
47
|
+
#
|
|
48
|
+
attr_accessor :volume_boot
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
# The name of the openstack project on witch the vm will be created.
|
|
52
|
+
#
|
|
53
|
+
attr_accessor :tenant_name
|
|
54
|
+
|
|
55
|
+
# The name of the server. This defaults to the name of the machine
|
|
56
|
+
# defined by Vagrant (via `config.vm.define`), but can be overriden
|
|
57
|
+
# here.
|
|
58
|
+
attr_accessor :server_name
|
|
59
|
+
|
|
60
|
+
# The username to access Openstack.
|
|
61
|
+
#
|
|
62
|
+
# @return [String]
|
|
63
|
+
attr_accessor :username
|
|
64
|
+
|
|
65
|
+
# The name of the keypair to use.
|
|
66
|
+
#
|
|
67
|
+
# @return [String]
|
|
68
|
+
attr_accessor :keypair_name
|
|
69
|
+
|
|
70
|
+
# The SSH username to use with this OpenStack instance. This overrides
|
|
71
|
+
# the `config.ssh.username` variable.
|
|
72
|
+
#
|
|
73
|
+
# @return [String]
|
|
74
|
+
attr_accessor :ssh_username
|
|
75
|
+
|
|
76
|
+
# The SSH timeout use after server creation. If server startup is too long
|
|
77
|
+
# the timeout value can be increase with this variable. Default is 60 seconds
|
|
78
|
+
#
|
|
79
|
+
# @return [Integer]
|
|
80
|
+
attr_accessor :ssh_timeout
|
|
81
|
+
|
|
82
|
+
# Opt files/directories in to the rsync operation performed by this provider
|
|
83
|
+
#
|
|
84
|
+
# @return [Array]
|
|
85
|
+
attr_accessor :rsync_includes
|
|
86
|
+
|
|
87
|
+
# The floating IP address from the IP pool which will be assigned to the instance.
|
|
88
|
+
#
|
|
89
|
+
# @return [String]
|
|
90
|
+
attr_accessor :floating_ip
|
|
91
|
+
|
|
92
|
+
# The floating IP pool from where new IPs will be allocated
|
|
93
|
+
#
|
|
94
|
+
# @return [String]
|
|
95
|
+
attr_accessor :floating_ip_pool
|
|
96
|
+
|
|
97
|
+
# if set to true, vagrant will always allocate floating ip instead of trying to reuse unassigned ones
|
|
98
|
+
# default to false
|
|
99
|
+
#
|
|
100
|
+
# @return [Boolean]
|
|
101
|
+
attr_accessor :floating_ip_pool_always_allocate
|
|
102
|
+
|
|
103
|
+
# Sync folder method. Can be either "rsync" or "none"
|
|
104
|
+
#
|
|
105
|
+
# @return [String]
|
|
106
|
+
attr_accessor :sync_method
|
|
107
|
+
|
|
108
|
+
# Sync folder ignore files. A list of files containing exclude patterns to ignore in the rsync operation
|
|
109
|
+
# performed by this provider
|
|
110
|
+
#
|
|
111
|
+
# @return [Array]
|
|
112
|
+
attr_accessor :rsync_ignore_files
|
|
113
|
+
|
|
114
|
+
# Network list the VM will be connected to
|
|
115
|
+
#
|
|
116
|
+
# @return [Array]
|
|
117
|
+
attr_accessor :networks
|
|
118
|
+
|
|
119
|
+
# Volumes list that will be attached to the VM
|
|
120
|
+
#
|
|
121
|
+
# @return [Array]
|
|
122
|
+
attr_accessor :volumes
|
|
123
|
+
|
|
124
|
+
# Stack that will be created and associated to the instances
|
|
125
|
+
#
|
|
126
|
+
# @return [Array]
|
|
127
|
+
attr_accessor :stacks
|
|
128
|
+
|
|
129
|
+
# Public key path to create OpenStack keypair
|
|
130
|
+
#
|
|
131
|
+
# @return [Array]
|
|
132
|
+
attr_accessor :public_key_path
|
|
133
|
+
|
|
134
|
+
# Availability Zone
|
|
135
|
+
#
|
|
136
|
+
# @return [String]
|
|
137
|
+
attr_accessor :availability_zone
|
|
138
|
+
|
|
139
|
+
# Pass hints to the OpenStack scheduler, e.g. { "cell": "some cell name" }
|
|
140
|
+
attr_accessor :scheduler_hints
|
|
141
|
+
|
|
142
|
+
# List of strings representing the security groups to apply.
|
|
143
|
+
# e.g. ['ssh', 'http']
|
|
144
|
+
#
|
|
145
|
+
# @return [Array[String]]
|
|
146
|
+
attr_accessor :security_groups
|
|
147
|
+
|
|
148
|
+
# User data to be sent to the newly created OpenStack instance. Use this
|
|
149
|
+
# e.g. to inject a script at boot time.
|
|
150
|
+
#
|
|
151
|
+
# @return [String]
|
|
152
|
+
attr_accessor :user_data
|
|
153
|
+
|
|
154
|
+
# A Hash of metadata that will be sent to the instance for configuration
|
|
155
|
+
#
|
|
156
|
+
# @return [Hash]
|
|
157
|
+
attr_accessor :metadata
|
|
158
|
+
|
|
159
|
+
# Flag to enable/disable all SSH actions (to use for instance on private networks)
|
|
160
|
+
#
|
|
161
|
+
# @return [Boolean]
|
|
162
|
+
attr_accessor :ssh_disabled
|
|
163
|
+
|
|
164
|
+
# Specify the endpoint_type to use : publicURL, adminURL, or internalURL (default is publicURL)
|
|
165
|
+
#
|
|
166
|
+
# @return [String]
|
|
167
|
+
attr_accessor :endpoint_type
|
|
168
|
+
|
|
169
|
+
#
|
|
170
|
+
# @return [Integer]
|
|
171
|
+
attr_accessor :server_create_timeout
|
|
172
|
+
|
|
173
|
+
#
|
|
174
|
+
# @return [Integer]
|
|
175
|
+
attr_accessor :server_active_timeout
|
|
176
|
+
|
|
177
|
+
#
|
|
178
|
+
# @return [Integer]
|
|
179
|
+
attr_accessor :server_stop_timeout
|
|
180
|
+
|
|
181
|
+
#
|
|
182
|
+
# @return [Integer]
|
|
183
|
+
attr_accessor :server_delete_timeout
|
|
184
|
+
|
|
185
|
+
#
|
|
186
|
+
# @return [Integer]
|
|
187
|
+
attr_accessor :stack_create_timeout
|
|
188
|
+
|
|
189
|
+
#
|
|
190
|
+
# @return [Integer]
|
|
191
|
+
attr_accessor :stack_delete_timeout
|
|
192
|
+
|
|
193
|
+
#
|
|
194
|
+
# @return [HttpConfig]
|
|
195
|
+
attr_accessor :http
|
|
196
|
+
|
|
197
|
+
def initialize
|
|
198
|
+
@password = UNSET_VALUE
|
|
199
|
+
@openstack_compute_url = UNSET_VALUE
|
|
200
|
+
@openstack_network_url = UNSET_VALUE
|
|
201
|
+
@openstack_volume_url = UNSET_VALUE
|
|
202
|
+
@openstack_orchestration_url = UNSET_VALUE
|
|
203
|
+
@openstack_image_url = UNSET_VALUE
|
|
204
|
+
@openstack_auth_url = UNSET_VALUE
|
|
205
|
+
@endpoint_type = UNSET_VALUE
|
|
206
|
+
@region = UNSET_VALUE
|
|
207
|
+
@flavor = UNSET_VALUE
|
|
208
|
+
@image = UNSET_VALUE
|
|
209
|
+
@volume_boot = UNSET_VALUE
|
|
210
|
+
@tenant_name = UNSET_VALUE
|
|
211
|
+
@server_name = UNSET_VALUE
|
|
212
|
+
@username = UNSET_VALUE
|
|
213
|
+
@rsync_includes = []
|
|
214
|
+
@rsync_ignore_files = []
|
|
215
|
+
@keypair_name = UNSET_VALUE
|
|
216
|
+
@ssh_username = UNSET_VALUE
|
|
217
|
+
@ssh_timeout = UNSET_VALUE
|
|
218
|
+
@floating_ip = UNSET_VALUE
|
|
219
|
+
@floating_ip_pool = []
|
|
220
|
+
@floating_ip_pool_always_allocate = UNSET_VALUE
|
|
221
|
+
@sync_method = UNSET_VALUE
|
|
222
|
+
@availability_zone = UNSET_VALUE
|
|
223
|
+
@networks = []
|
|
224
|
+
@stacks = []
|
|
225
|
+
@volumes = []
|
|
226
|
+
@public_key_path = UNSET_VALUE
|
|
227
|
+
@scheduler_hints = UNSET_VALUE
|
|
228
|
+
@security_groups = UNSET_VALUE
|
|
229
|
+
@user_data = UNSET_VALUE
|
|
230
|
+
@metadata = UNSET_VALUE
|
|
231
|
+
@ssh_disabled = UNSET_VALUE
|
|
232
|
+
@server_create_timeout = UNSET_VALUE
|
|
233
|
+
@server_active_timeout = UNSET_VALUE
|
|
234
|
+
@server_stop_timeout = UNSET_VALUE
|
|
235
|
+
@server_delete_timeout = UNSET_VALUE
|
|
236
|
+
@stack_create_timeout = UNSET_VALUE
|
|
237
|
+
@stack_delete_timeout = UNSET_VALUE
|
|
238
|
+
@http = HttpConfig.new
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def merge(other)
|
|
242
|
+
result = self.class.new
|
|
243
|
+
|
|
244
|
+
# Set all of our instance variables on the new class
|
|
245
|
+
[self, other].each do |obj|
|
|
246
|
+
obj.instance_variables.each do |key|
|
|
247
|
+
# Ignore keys that start with a double underscore. This allows
|
|
248
|
+
# configuration classes to still hold around internal state
|
|
249
|
+
# that isn't propagated.
|
|
250
|
+
next if key.to_s.start_with?('@__')
|
|
251
|
+
|
|
252
|
+
# Let user inputs a string or an array for floating ip pool attribute
|
|
253
|
+
obj.floating_ip_pool = [obj.floating_ip_pool].flatten if key.eql?(:@floating_ip_pool) && !obj.floating_ip_pool.nil?
|
|
254
|
+
|
|
255
|
+
# Let user inputs a string or an array for networks attribute
|
|
256
|
+
obj.networks = [obj.networks].flatten if key.eql?(:@networks) && !obj.networks.nil?
|
|
257
|
+
|
|
258
|
+
# Don't set the value if it is the unset value, either.
|
|
259
|
+
value = obj.instance_variable_get(key)
|
|
260
|
+
|
|
261
|
+
if [:@networks, :@volumes, :@rsync_includes, :@rsync_ignore_files, :@floating_ip_pool, :@stacks].include? key
|
|
262
|
+
result.instance_variable_set(key, value) unless value.empty?
|
|
263
|
+
elsif [:@http].include? key
|
|
264
|
+
result.instance_variable_set(key, instance_variable_get(key).merge(other.instance_variable_get(key))) if value != UNSET_VALUE
|
|
265
|
+
else
|
|
266
|
+
result.instance_variable_set(key, value) if value != UNSET_VALUE
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# Persist through the set of invalid methods
|
|
272
|
+
this_invalid = @__invalid_methods || Set.new
|
|
273
|
+
other_invalid = other.instance_variable_get(:"@__invalid_methods") || Set.new
|
|
274
|
+
result.instance_variable_set(:"@__invalid_methods", this_invalid + other_invalid)
|
|
275
|
+
|
|
276
|
+
result
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
280
|
+
def finalize!
|
|
281
|
+
@password = nil if @password == UNSET_VALUE
|
|
282
|
+
@openstack_compute_url = nil if @openstack_compute_url == UNSET_VALUE
|
|
283
|
+
@openstack_network_url = nil if @openstack_network_url == UNSET_VALUE
|
|
284
|
+
@openstack_orchestration_url = nil if @openstack_orchestration_url == UNSET_VALUE
|
|
285
|
+
@openstack_volume_url = nil if @openstack_volume_url == UNSET_VALUE
|
|
286
|
+
@openstack_image_url = nil if @openstack_image_url == UNSET_VALUE
|
|
287
|
+
@openstack_auth_url = nil if @openstack_auth_url == UNSET_VALUE
|
|
288
|
+
@endpoint_type = 'publicURL' if @endpoint_type == UNSET_VALUE
|
|
289
|
+
@region = nil if @region == UNSET_VALUE
|
|
290
|
+
@flavor = nil if @flavor == UNSET_VALUE
|
|
291
|
+
@image = nil if @image == UNSET_VALUE
|
|
292
|
+
@volume_boot = nil if @volume_boot == UNSET_VALUE
|
|
293
|
+
@tenant_name = nil if @tenant_name == UNSET_VALUE
|
|
294
|
+
@server_name = nil if @server_name == UNSET_VALUE
|
|
295
|
+
@username = nil if @username == UNSET_VALUE
|
|
296
|
+
@rsync_includes = nil if @rsync_includes.empty?
|
|
297
|
+
@rsync_ignore_files = nil if @rsync_ignore_files.empty?
|
|
298
|
+
@floating_ip = nil if @floating_ip == UNSET_VALUE
|
|
299
|
+
@floating_ip_pool = nil if @floating_ip_pool == UNSET_VALUE
|
|
300
|
+
@floating_ip_pool_always_allocate = false if floating_ip_pool_always_allocate == UNSET_VALUE
|
|
301
|
+
@sync_method = 'rsync' if @sync_method == UNSET_VALUE
|
|
302
|
+
@keypair_name = nil if @keypair_name == UNSET_VALUE
|
|
303
|
+
@public_key_path = nil if @public_key_path == UNSET_VALUE
|
|
304
|
+
@availability_zone = nil if @availability_zone == UNSET_VALUE
|
|
305
|
+
@scheduler_hints = nil if @scheduler_hints == UNSET_VALUE
|
|
306
|
+
@security_groups = nil if @security_groups == UNSET_VALUE
|
|
307
|
+
@user_data = nil if @user_data == UNSET_VALUE
|
|
308
|
+
@metadata = nil if @metadata == UNSET_VALUE
|
|
309
|
+
@ssh_disabled = false if @ssh_disabled == UNSET_VALUE
|
|
310
|
+
|
|
311
|
+
# The SSH values by default are nil, and the top-level config
|
|
312
|
+
# `config.ssh` values are used.
|
|
313
|
+
@ssh_username = nil if @ssh_username == UNSET_VALUE
|
|
314
|
+
@ssh_timeout = 180 if @ssh_timeout == UNSET_VALUE
|
|
315
|
+
@server_create_timeout = 200 if @server_create_timeout == UNSET_VALUE
|
|
316
|
+
@server_active_timeout = 200 if @server_active_timeout == UNSET_VALUE
|
|
317
|
+
@server_stop_timeout = 200 if @server_stop_timeout == UNSET_VALUE
|
|
318
|
+
@server_delete_timeout = 200 if @server_delete_timeout == UNSET_VALUE
|
|
319
|
+
@stack_create_timeout = 200 if @stack_create_timeout == UNSET_VALUE
|
|
320
|
+
@stack_delete_timeout = 200 if @stack_delete_timeout == UNSET_VALUE
|
|
321
|
+
@networks = nil if @networks.empty?
|
|
322
|
+
@volumes = nil if @volumes.empty?
|
|
323
|
+
@stacks = nil if @stacks.empty?
|
|
324
|
+
@http.finalize!
|
|
325
|
+
end
|
|
326
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
327
|
+
|
|
328
|
+
def rsync_include(inc)
|
|
329
|
+
@rsync_includes << inc
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def validate(machine)
|
|
333
|
+
errors = _detected_errors
|
|
334
|
+
|
|
335
|
+
errors << I18n.t('vagrant_openstack.config.password_required') if @password.nil? || @password.empty?
|
|
336
|
+
errors << I18n.t('vagrant_openstack.config.username_required') if @username.nil? || @username.empty?
|
|
337
|
+
errors << I18n.t('vagrant_openstack.config.tenant_name_required') if @tenant_name.nil? || @tenant_name.empty?
|
|
338
|
+
errors << I18n.t('vagrant_openstack.config.invalid_endpoint_type') unless %w(publicURL adminURL internalURL).include?(@endpoint_type)
|
|
339
|
+
|
|
340
|
+
validate_ssh_username(machine, errors)
|
|
341
|
+
validate_stack_config(errors)
|
|
342
|
+
validate_ssh_timeout(errors)
|
|
343
|
+
|
|
344
|
+
if machine.config.ssh.private_key_path
|
|
345
|
+
puts I18n.t('vagrant_openstack.config.keypair_name_required').yellow unless @keypair_name || @public_key_path
|
|
346
|
+
else
|
|
347
|
+
errors << I18n.t('vagrant_openstack.config.private_key_missing') if @keypair_name || @public_key_path
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
{
|
|
351
|
+
openstack_compute_url: @openstack_compute_url,
|
|
352
|
+
openstack_network_url: @openstack_network_url,
|
|
353
|
+
openstack_volume_url: @openstack_volume_url,
|
|
354
|
+
openstack_orchestration_url: @openstack_orchestration_url,
|
|
355
|
+
openstack_image_url: @openstack_image_url,
|
|
356
|
+
openstack_auth_url: @openstack_auth_url
|
|
357
|
+
}.each_pair do |key, value|
|
|
358
|
+
errors << I18n.t('vagrant_openstack.config.invalid_uri', key: key, uri: value) unless value.nil? || valid_uri?(value)
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
{ 'Openstack Provider' => errors }
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
private
|
|
365
|
+
|
|
366
|
+
def validate_stack_config(errors)
|
|
367
|
+
@stacks.each do |stack|
|
|
368
|
+
errors << I18n.t('vagrant_openstack.config.invalid_stack') unless stack[:name] && stack[:template]
|
|
369
|
+
end unless @stacks.nil?
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def validate_ssh_username(machine, errors)
|
|
373
|
+
puts I18n.t('vagrant_openstack.config.ssh_username_deprecated').yellow if @ssh_username
|
|
374
|
+
errors << I18n.t('vagrant_openstack.config.ssh_username_required') unless @ssh_username || machine.config.ssh.username
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def validate_ssh_timeout(errors)
|
|
378
|
+
return if @ssh_timeout.nil? || @ssh_timeout == UNSET_VALUE
|
|
379
|
+
@ssh_timeout = Integer(@ssh_timeout) if @ssh_timeout.is_a? String
|
|
380
|
+
rescue ArgumentError
|
|
381
|
+
errors << I18n.t('vagrant_openstack.config.invalid_value_for_parameter', parameter: 'ssh_timeout', value: @ssh_timeout)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def valid_uri?(value)
|
|
385
|
+
uri = URI.parse value
|
|
386
|
+
uri.is_a?(URI::HTTP)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|