vagrant-openstack-provider 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +8 -8
  2. data/Appraisals +6 -6
  3. data/CHANGELOG.md +44 -1
  4. data/Gemfile +10 -6
  5. data/Vagrantfile +7 -15
  6. data/functional_tests/Vagrantfile +58 -0
  7. data/functional_tests/keys/vagrant-openstack +27 -0
  8. data/functional_tests/keys/vagrant-openstack.pub +1 -0
  9. data/functional_tests/run_tests.sh +142 -0
  10. data/gemfiles/latest_stable.gemfile +5 -0
  11. data/gemfiles/oldest_current.gemfile +5 -0
  12. data/gemfiles/previous_release.gemfile +5 -0
  13. data/lib/vagrant-openstack-provider/action.rb +17 -2
  14. data/lib/vagrant-openstack-provider/action/connect_openstack.rb +60 -8
  15. data/lib/vagrant-openstack-provider/action/create_server.rb +131 -43
  16. data/lib/vagrant-openstack-provider/action/delete_server.rb +2 -0
  17. data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +22 -3
  18. data/lib/vagrant-openstack-provider/action/resume.rb +2 -0
  19. data/lib/vagrant-openstack-provider/action/stop_server.rb +1 -0
  20. data/lib/vagrant-openstack-provider/action/suspend.rb +2 -0
  21. data/lib/vagrant-openstack-provider/action/sync_folders.rb +3 -2
  22. data/lib/vagrant-openstack-provider/action/wait_active.rb +29 -0
  23. data/lib/vagrant-openstack-provider/action/wait_stop.rb +1 -1
  24. data/lib/vagrant-openstack-provider/client/domain.rb +26 -0
  25. data/lib/vagrant-openstack-provider/client/http_utils.rb +96 -0
  26. data/lib/vagrant-openstack-provider/client/keystone.rb +30 -41
  27. data/lib/vagrant-openstack-provider/client/neutron.rb +24 -11
  28. data/lib/vagrant-openstack-provider/client/nova.rb +99 -104
  29. data/lib/vagrant-openstack-provider/client/openstack.rb +4 -0
  30. data/lib/vagrant-openstack-provider/client/request_logger.rb +24 -0
  31. data/lib/vagrant-openstack-provider/command/abstract_command.rb +31 -0
  32. data/lib/vagrant-openstack-provider/command/flavor_list.rb +21 -0
  33. data/lib/vagrant-openstack-provider/command/floatingip_list.rb +34 -0
  34. data/lib/vagrant-openstack-provider/command/image_list.rb +21 -0
  35. data/lib/vagrant-openstack-provider/command/main.rb +51 -0
  36. data/lib/vagrant-openstack-provider/command/network_list.rb +21 -0
  37. data/lib/vagrant-openstack-provider/command/utils.rb +22 -0
  38. data/lib/vagrant-openstack-provider/config.rb +31 -3
  39. data/lib/vagrant-openstack-provider/errors.rb +28 -0
  40. data/lib/vagrant-openstack-provider/plugin.rb +5 -0
  41. data/lib/vagrant-openstack-provider/version.rb +1 -1
  42. data/locales/en.yml +45 -1
  43. data/spec/vagrant-openstack-provider/action/connect_openstack_spec.rb +190 -0
  44. data/spec/vagrant-openstack-provider/action/create_server_spec.rb +166 -1
  45. data/spec/vagrant-openstack-provider/action/read_ssh_info_spec.rb +109 -0
  46. data/spec/vagrant-openstack-provider/client/keystone_spec.rb +32 -48
  47. data/spec/vagrant-openstack-provider/client/neutron_spec.rb +42 -4
  48. data/spec/vagrant-openstack-provider/client/nova_spec.rb +247 -6
  49. data/spec/vagrant-openstack-provider/client/utils_spec.rb +58 -5
  50. data/spec/vagrant-openstack-provider/command/floatingip_list_spec.rb +67 -0
  51. data/spec/vagrant-openstack-provider/config_spec.rb +21 -6
  52. data/spec/vagrant-openstack-provider/spec_helper.rb +7 -0
  53. data/{numergyrc → stackrc} +4 -1
  54. metadata +24 -4
  55. data/lib/vagrant-openstack-provider/client/utils.rb +0 -38
@@ -20,6 +20,10 @@ module VagrantPlugins
20
20
  @project_id = nil
21
21
  @endpoints = {}
22
22
  end
23
+
24
+ def reset
25
+ initialize
26
+ end
23
27
  end
24
28
 
25
29
  def self.session
@@ -0,0 +1,24 @@
1
+ require 'log4r'
2
+ require 'restclient'
3
+ require 'json'
4
+
5
+ module VagrantPlugins
6
+ module Openstack
7
+ module HttpUtils
8
+ module RequestLogger
9
+ def log_request(method, url, body = nil, headers)
10
+ @logger.debug "request => method : #{method}"
11
+ @logger.debug "request => url : #{url}"
12
+ @logger.debug "request => headers : #{headers}"
13
+ @logger.debug "request => body : #{body}" unless body.nil?
14
+ end
15
+
16
+ def log_response(response)
17
+ @logger.debug "response => code : #{response.code}"
18
+ @logger.debug "response => headers : #{response.headers}"
19
+ @logger.debug "response => body : #{response}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ require 'vagrant-openstack-provider/client/openstack'
2
+
3
+ module VagrantPlugins
4
+ module Openstack
5
+ module Command
6
+ class AbstractCommand < Vagrant.plugin('2', :command)
7
+ def initialize(argv, env)
8
+ @env = env
9
+ super(argv, env)
10
+ end
11
+
12
+ def execute(name)
13
+ env = {}
14
+ with_target_vms(nil, provider: :openstack) do |machine|
15
+ env[:machine] = machine
16
+ env[:ui] = @env.ui
17
+ end
18
+
19
+ VagrantPlugins::Openstack::Action::ConnectOpenstack.new(nil, env).call(env)
20
+
21
+ cmd(name, @argv, env)
22
+ @env.ui.info('')
23
+ end
24
+
25
+ def cmd(_name, _argv, _env)
26
+ fail 'Command not implemented. \'cmd\' method must be overridden in all subclasses'
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ require 'vagrant-openstack-provider/command/utils'
2
+ require 'vagrant-openstack-provider/command/abstract_command'
3
+
4
+ module VagrantPlugins
5
+ module Openstack
6
+ module Command
7
+ class FlavorList < AbstractCommand
8
+ include VagrantPlugins::Openstack::Command::Utils
9
+
10
+ def self.synopsis
11
+ I18n.t('vagrant_openstack.command.flavor_list_synopsis')
12
+ end
13
+ def cmd(name, argv, env)
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 1
15
+ flavors = env[:openstack_client].nova.get_all_flavors(env)
16
+ display_item_list(env, flavors)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ require 'vagrant-openstack-provider/command/utils'
2
+ require 'vagrant-openstack-provider/command/abstract_command'
3
+
4
+ module VagrantPlugins
5
+ module Openstack
6
+ module Command
7
+ class FloatingIpList < AbstractCommand
8
+ include VagrantPlugins::Openstack::Command::Utils
9
+
10
+ def self.synopsis
11
+ I18n.t('vagrant_openstack.command.flaotingip_list_synopsis')
12
+ end
13
+ def cmd(name, argv, env)
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 1
15
+
16
+ floating_ip_pools = env[:openstack_client].nova.get_floating_ip_pools(env)
17
+ floating_ips = env[:openstack_client].nova.get_floating_ips(env)
18
+
19
+ rows = []
20
+ floating_ip_pools.each do |floating_ip_pool|
21
+ rows << [floating_ip_pool['name']]
22
+ end
23
+ display_table(env, ['Floating IP pools'], rows)
24
+
25
+ rows = []
26
+ floating_ips.each do |floating_ip|
27
+ rows << [floating_ip['id'], floating_ip['ip'], floating_ip['pool'], floating_ip['instance_id']]
28
+ end
29
+ display_table(env, ['Id', 'IP', 'Pool', 'Instance id'], rows)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,21 @@
1
+ require 'vagrant-openstack-provider/command/utils'
2
+ require 'vagrant-openstack-provider/command/abstract_command'
3
+
4
+ module VagrantPlugins
5
+ module Openstack
6
+ module Command
7
+ class ImageList < AbstractCommand
8
+ include VagrantPlugins::Openstack::Command::Utils
9
+
10
+ def self.synopsis
11
+ I18n.t('vagrant_openstack.command.image_list_synopsis')
12
+ end
13
+ def cmd(name, argv, env)
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 1
15
+ images = env[:openstack_client].nova.get_all_images(env)
16
+ display_item_list(env, images)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,51 @@
1
+ module VagrantPlugins
2
+ module Openstack
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: :'floatingip-list', file: 'floatingip_list', clazz: 'FloatingIpList' }
9
+ ]
10
+
11
+ class Main < Vagrant.plugin('2', :command)
12
+ def self.synopsis
13
+ Openstack.init_i18n
14
+ I18n.t('vagrant_openstack.command.main_synopsis')
15
+ end
16
+
17
+ def initialize(argv, env)
18
+ @env = env
19
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
20
+ @commands = Vagrant::Registry.new
21
+
22
+ COMMANDS.each do |cmd|
23
+ @commands.register(cmd[:name]) do
24
+ require_relative cmd[:file]
25
+ Command.const_get(cmd[:clazz])
26
+ end
27
+ end
28
+
29
+ super(argv, env)
30
+ end
31
+
32
+ def execute
33
+ Openstack.init_i18n
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,21 @@
1
+ require 'vagrant-openstack-provider/command/utils'
2
+ require 'vagrant-openstack-provider/command/abstract_command'
3
+
4
+ module VagrantPlugins
5
+ module Openstack
6
+ module Command
7
+ class NetworkList < AbstractCommand
8
+ include VagrantPlugins::Openstack::Command::Utils
9
+
10
+ def self.synopsis
11
+ I18n.t('vagrant_openstack.command.network_list_synopsis')
12
+ end
13
+ def cmd(name, argv, env)
14
+ fail Errors::NoArgRequiredForCommand, cmd: name unless argv.size == 1
15
+ flavors = env[:openstack_client].neutron.get_private_networks(env)
16
+ display_item_list(env, flavors)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ require 'terminal-table'
2
+
3
+ module VagrantPlugins
4
+ module Openstack
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}\n")
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,4 +1,5 @@
1
1
  require 'vagrant'
2
+ require 'colorize'
2
3
 
3
4
  module VagrantPlugins
4
5
  module Openstack
@@ -70,6 +71,11 @@ module VagrantPlugins
70
71
  # @return [String]
71
72
  attr_accessor :floating_ip
72
73
 
74
+ # The floating IP pool from where new IPs will be allocated
75
+ #
76
+ # @return [String]
77
+ attr_accessor :floating_ip_pool
78
+
73
79
  # Sync folder method. Can be either "rsync" or "none"
74
80
  #
75
81
  # @return [String]
@@ -80,6 +86,16 @@ module VagrantPlugins
80
86
  # @return [Array]
81
87
  attr_accessor :networks
82
88
 
89
+ # Public key path to create OpenStack keypair
90
+ #
91
+ # @return [Array]
92
+ attr_accessor :public_key_path
93
+
94
+ # Availability Zone
95
+ #
96
+ # @return [String]
97
+ attr_accessor :availability_zone
98
+
83
99
  def initialize
84
100
  @password = UNSET_VALUE
85
101
  @openstack_compute_url = UNSET_VALUE
@@ -95,8 +111,11 @@ module VagrantPlugins
95
111
  @ssh_username = UNSET_VALUE
96
112
  @ssh_timeout = UNSET_VALUE
97
113
  @floating_ip = UNSET_VALUE
114
+ @floating_ip_pool = UNSET_VALUE
98
115
  @sync_method = UNSET_VALUE
116
+ @availability_zone = UNSET_VALUE
99
117
  @networks = []
118
+ @public_key_path = UNSET_VALUE
100
119
  end
101
120
 
102
121
  # rubocop:disable Style/CyclomaticComplexity
@@ -112,8 +131,11 @@ module VagrantPlugins
112
131
  @username = nil if @username == UNSET_VALUE
113
132
  @rsync_includes = nil if @rsync_includes.empty?
114
133
  @floating_ip = nil if @floating_ip == UNSET_VALUE
134
+ @floating_ip_pool = nil if @floating_ip_pool == UNSET_VALUE
115
135
  @sync_method = 'rsync' if @sync_method == UNSET_VALUE
116
136
  @keypair_name = nil if @keypair_name == UNSET_VALUE
137
+ @public_key_path = nil if @public_key_path == UNSET_VALUE
138
+ @availability_zone = nil if @availability_zone == UNSET_VALUE
117
139
 
118
140
  # The SSH values by default are nil, and the top-level config
119
141
  # `config.ssh` values are used.
@@ -127,12 +149,18 @@ module VagrantPlugins
127
149
  @rsync_includes << inc
128
150
  end
129
151
 
130
- def validate(_machine)
152
+ def validate(machine)
131
153
  errors = _detected_errors
132
154
 
133
155
  errors << I18n.t('vagrant_openstack.config.password_required') unless @password
134
156
  errors << I18n.t('vagrant_openstack.config.username_required') unless @username
135
- errors << I18n.t('vagrant_openstack.config.keypair_name_required') unless @keypair_name
157
+
158
+ if machine.config.ssh.private_key_path
159
+ # Waiting for https://github.com/mitchellh/vagrant/issues/4388 to improve this
160
+ puts I18n.t('vagrant_openstack.config.keypair_name_required').yellow unless @keypair_name || @public_key_path
161
+ else
162
+ errors << I18n.t('vagrant_openstack.config.private_key_missing') if @keypair_name || @public_key_path
163
+ end
136
164
 
137
165
  {
138
166
  openstack_compute_url: @openstack_compute_url,
@@ -149,7 +177,7 @@ module VagrantPlugins
149
177
 
150
178
  def valid_uri?(value)
151
179
  uri = URI.parse value
152
- uri.kind_of?(URI::HTTP)
180
+ uri.is_a?(URI::HTTP)
153
181
  end
154
182
  end
155
183
  end
@@ -12,6 +12,18 @@ module VagrantPlugins
12
12
  error_key(:authentication_required)
13
13
  end
14
14
 
15
+ class AuthenticationFailed < VagrantOpenstackError
16
+ error_key(:authentication_failed)
17
+ end
18
+
19
+ class BadAuthenticationEndpoint < VagrantOpenstackError
20
+ error_key(:bad_authentication_endpoint)
21
+ end
22
+
23
+ class MultipleApiVersion < VagrantOpenstackError
24
+ error_key(:multiple_api_version)
25
+ end
26
+
15
27
  class CreateBadState < VagrantOpenstackError
16
28
  error_key(:create_bad_state)
17
29
  end
@@ -35,6 +47,22 @@ module VagrantPlugins
35
47
  class SshUnavailable < VagrantOpenstackError
36
48
  error_key(:ssh_unavailble)
37
49
  end
50
+
51
+ class NoArgRequiredForCommand < VagrantOpenstackError
52
+ error_key(:no_arg_required_for_command)
53
+ end
54
+
55
+ class UnableToResolveFloatingIP < VagrantOpenstackError
56
+ error_key(:unable_to_resolve_floating_ip)
57
+ end
58
+
59
+ class UnableToResolveIP < VagrantOpenstackError
60
+ error_key(:unable_to_resolve_ip)
61
+ end
62
+
63
+ class UnableToResolveSSHKey < VagrantOpenstackError
64
+ error_key(:unable_to_resolve_ssh_key)
65
+ end
38
66
  end
39
67
  end
40
68
  end
@@ -32,6 +32,11 @@ module VagrantPlugins
32
32
  require_relative 'provider'
33
33
  Provider
34
34
  end
35
+
36
+ command('openstack') do
37
+ require_relative 'command/main'
38
+ Command::Main
39
+ end
35
40
  end
36
41
  end
37
42
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Openstack
3
- VERSION = '0.2.0'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
data/locales/en.yml CHANGED
@@ -28,12 +28,16 @@ en:
28
28
  Trying authentication...
29
29
  rsync_folder: |-
30
30
  Rsyncing folder: %{hostpath} => %{guestpath}
31
+ using_floating_ip: |-
32
+ Using floating IP %{floating_ip}
31
33
  waiting_for_build: |-
32
34
  Waiting for the server to be built...
33
35
  waiting_for_ssh: |-
34
36
  Waiting for SSH to become available...
35
37
  waiting_stop: |-
36
38
  Waiting for the server to stop...
39
+ waiting_start: |-
40
+ Waiting for the server to start...
37
41
  warn_networks: |-
38
42
  Warning! The Openstack provider doesn't support any of the Vagrant
39
43
  high-level network configurations (`config.vm.network`). They
@@ -49,18 +53,34 @@ en:
49
53
  metadata_must_be_hash: |-
50
54
  Metadata must be a hash.
51
55
  keypair_name_required: |-
52
- A keypair name is required.
56
+ Warning! You have specified ssh.private_key_path in your Vagrant configuration.
57
+ but nor keypair_name neither public_key_path are present. The openstack provider
58
+ will automatically generate a new keypair and your configuration option
59
+ ssh.private_key_path will be overriden
60
+ private_key_missing: |-
61
+ config.ssh.private_key_path is required when either keypair_name or
62
+ public_key_path is set in Vagrantfile
53
63
 
54
64
  errors:
55
65
  default: |-
56
66
  %{message}
57
67
  authentication_required: |-
58
68
  Authentication token is missing or no longer valid.
69
+ authentication_failed: |-
70
+ Authentication failed.
71
+ bad_authentication_endpoint: |-
72
+ Bad authentication endpoint.
59
73
  create_bad_state: |-
60
74
  While creating the server, it transitioned to an unexpected
61
75
  state: '%{state}', instead of properly booting. Run `vagrant status`
62
76
  to find out what can be done about this state, or `vagrant destroy`
63
77
  if you want to start over.
78
+ multiple_api_version: |-
79
+ Multiple version found for %{api_name} API
80
+
81
+ %{version_list}
82
+ You must specify the desired network API url by setting
83
+ the provider's property '%{url_property}'.
64
84
  no_matching_flavor: |-
65
85
  No matching flavor was found! Please check your flavor setting
66
86
  to make sure you have a valid flavor chosen.
@@ -78,6 +98,14 @@ en:
78
98
  Error: %{stderr}
79
99
  ssh_unavailble: |-
80
100
  SSH server anavailable on instance %{host}. You should maybe increase the timeout value which currently is %{timeout} second(s).
101
+ no_arg_required_for_command: |-
102
+ Command '%{cmd}' does not required any argument.
103
+ unable_to_resolve_floating_ip: |-
104
+ Vagrant was unable to resolve a floating ip to communicate with your OpenStack instance. Please specify in your Vagrantfile either `floating_ip` or `floating_ip_pool`.
105
+ unable_to_resolve_ip: |-
106
+ Vagrant was unable to resolve a valid ip to ssh on your OpenStack instance.
107
+ unable_to_resolve_ssh_key: |-
108
+ Vagrant was unable to resolve a valid ssh key to connect to your OpenStack instance. Please specify in your Vagrantfile either `public_key_path` or `keypair_name`.
81
109
 
82
110
  states:
83
111
  short_active: |-
@@ -161,3 +189,19 @@ en:
161
189
  %{size} endpoints are available for service '%{type}' but only the first one will be used
162
190
  authentication: |-
163
191
  Authentication on project %{project} with user %{user}
192
+
193
+ command:
194
+ main_synopsis: |-
195
+ Openstack provider specific commands
196
+ main_usage : |-
197
+ Usage: vagrant openstack command
198
+ available_subcommands: |-
199
+ Available subcommands:
200
+ image_list_synopsis : |-
201
+ List available images
202
+ flavor_list_synopsis : |-
203
+ List available flavors
204
+ network_list_synopsis : |-
205
+ List private networks in project
206
+ flaotingip_list_synopsis : |-
207
+ List floating IP and floating IP pools