vagrant-openstack-provider 0.2.0 → 0.3.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.
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