vagrant-openstack-provider 0.5.2 → 0.6.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/lib/vagrant-openstack-provider.rb +2 -31
  4. data/lib/vagrant-openstack-provider/action.rb +21 -7
  5. data/lib/vagrant-openstack-provider/action/abstract_action.rb +22 -0
  6. data/lib/vagrant-openstack-provider/action/connect_openstack.rb +19 -40
  7. data/lib/vagrant-openstack-provider/action/create_server.rb +10 -6
  8. data/lib/vagrant-openstack-provider/action/create_stack.rb +67 -0
  9. data/lib/vagrant-openstack-provider/action/delete_server.rb +28 -3
  10. data/lib/vagrant-openstack-provider/action/delete_stack.rb +72 -0
  11. data/lib/vagrant-openstack-provider/action/message.rb +4 -2
  12. data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +4 -2
  13. data/lib/vagrant-openstack-provider/action/read_state.rb +9 -4
  14. data/lib/vagrant-openstack-provider/action/resume.rb +4 -2
  15. data/lib/vagrant-openstack-provider/action/start_server.rb +4 -2
  16. data/lib/vagrant-openstack-provider/action/stop_server.rb +4 -2
  17. data/lib/vagrant-openstack-provider/action/suspend.rb +4 -2
  18. data/lib/vagrant-openstack-provider/action/sync_folders.rb +17 -13
  19. data/lib/vagrant-openstack-provider/action/wait_accessible.rb +5 -2
  20. data/lib/vagrant-openstack-provider/action/wait_active.rb +5 -3
  21. data/lib/vagrant-openstack-provider/action/wait_stop.rb +5 -3
  22. data/lib/vagrant-openstack-provider/catalog/openstack_catalog.rb +66 -0
  23. data/lib/vagrant-openstack-provider/client/domain.rb +41 -1
  24. data/lib/vagrant-openstack-provider/client/glance.rb +63 -0
  25. data/lib/vagrant-openstack-provider/client/heat.rb +50 -0
  26. data/lib/vagrant-openstack-provider/client/http_utils.rb +18 -0
  27. data/lib/vagrant-openstack-provider/client/neutron.rb +9 -15
  28. data/lib/vagrant-openstack-provider/client/nova.rb +3 -3
  29. data/lib/vagrant-openstack-provider/client/openstack.rb +10 -0
  30. data/lib/vagrant-openstack-provider/command/abstract_command.rb +7 -0
  31. data/lib/vagrant-openstack-provider/command/image_list.rb +12 -2
  32. data/lib/vagrant-openstack-provider/command/main.rb +1 -0
  33. data/lib/vagrant-openstack-provider/command/network_list.rb +3 -3
  34. data/lib/vagrant-openstack-provider/command/subnet_list.rb +25 -0
  35. data/lib/vagrant-openstack-provider/config.rb +78 -7
  36. data/lib/vagrant-openstack-provider/config_resolver.rb +36 -5
  37. data/lib/vagrant-openstack-provider/errors.rb +30 -2
  38. data/lib/vagrant-openstack-provider/logging.rb +39 -0
  39. data/lib/vagrant-openstack-provider/version.rb +1 -1
  40. data/locales/en.yml +107 -4
  41. data/spec/vagrant-openstack-provider/action/connect_openstack_spec.rb +255 -8
  42. data/spec/vagrant-openstack-provider/action/create_server_spec.rb +6 -1
  43. data/spec/vagrant-openstack-provider/action/create_stack_spec.rb +97 -0
  44. data/spec/vagrant-openstack-provider/action/delete_server_spec.rb +34 -6
  45. data/spec/vagrant-openstack-provider/action/delete_stack_spec.rb +64 -0
  46. data/spec/vagrant-openstack-provider/action/read_state_spec.rb +13 -1
  47. data/spec/vagrant-openstack-provider/action/sync_folders_spec.rb +1 -0
  48. data/spec/vagrant-openstack-provider/action/wait_active_spec.rb +1 -1
  49. data/spec/vagrant-openstack-provider/action/wait_stop_spec.rb +1 -1
  50. data/spec/vagrant-openstack-provider/client/glance_spec.rb +128 -0
  51. data/spec/vagrant-openstack-provider/client/heat_spec.rb +124 -0
  52. data/spec/vagrant-openstack-provider/client/neutron_spec.rb +33 -1
  53. data/spec/vagrant-openstack-provider/client/nova_spec.rb +2 -2
  54. data/spec/vagrant-openstack-provider/command/image_list_spec.rb +75 -23
  55. data/spec/vagrant-openstack-provider/command/subnet_list_spec.rb +46 -0
  56. data/spec/vagrant-openstack-provider/config_resolver_spec.rb +85 -19
  57. data/spec/vagrant-openstack-provider/config_spec.rb +177 -1
  58. data/spec/vagrant-openstack-provider/spec_helper.rb +3 -0
  59. metadata +20 -2
@@ -0,0 +1,72 @@
1
+ require 'log4r'
2
+ require 'socket'
3
+ require 'timeout'
4
+ require 'sshkey'
5
+ require 'yaml'
6
+
7
+ require 'vagrant-openstack-provider/config_resolver'
8
+ require 'vagrant-openstack-provider/utils'
9
+ require 'vagrant-openstack-provider/action/abstract_action'
10
+ require 'vagrant/util/retryable'
11
+
12
+ module VagrantPlugins
13
+ module Openstack
14
+ module Action
15
+ class DeleteStack < AbstractAction
16
+ def initialize(app, _env)
17
+ @app = app
18
+ @logger = Log4r::Logger.new('vagrant_openstack::action::delete_stack')
19
+ end
20
+
21
+ def execute(env)
22
+ @logger.info 'Start delete stacks action'
23
+
24
+ heat = env[:openstack_client].heat
25
+
26
+ list_stack_files(env).each do |stack|
27
+ env[:ui].info(I18n.t('vagrant_openstack.delete_stack'))
28
+ env[:ui].info(" -- Stack Name : #{stack[:name]}")
29
+ env[:ui].info(" -- Stack Id : #{stack[:id]}")
30
+
31
+ heat.delete_stack(env, stack[:name], stack[:id])
32
+
33
+ waiting_for_stack_to_be_deleted(env, stack[:name], stack[:id])
34
+ end
35
+
36
+ # This will remove all files in the .vagrant instance directory
37
+ env[:machine].id = nil
38
+
39
+ @app.call(env)
40
+ end
41
+
42
+ private
43
+
44
+ def list_stack_files(env)
45
+ stack_files = []
46
+ Dir.glob("#{env[:machine].data_dir}/stack_*_id") do |stack_file|
47
+ file_name = stack_file.split('/')[-1]
48
+ stack_files << {
49
+ name: file_name[6, (file_name.length) - 9],
50
+ id: File.read("#{stack_file}")
51
+ }
52
+ end
53
+ stack_files
54
+ end
55
+
56
+ def waiting_for_stack_to_be_deleted(env, stack_name, stack_id, retry_interval = 3, timeout = 200)
57
+ @logger.info "Waiting for the stack with id #{stack_id} to be deleted..."
58
+ env[:ui].info(I18n.t('vagrant_openstack.waiting_for_stack_deleted'))
59
+ timeout(timeout, Errors::Timeout) do
60
+ stack_status = 'DELETE_IN_PROGRESS'
61
+ until stack_status == 'DELETE_COMPLETE'
62
+ @logger.debug('Waiting for stack to be DELETED')
63
+ stack_status = env[:openstack_client].heat.get_stack_details(env, stack_name, stack_id)['stack_status']
64
+ fail Errors::StackStatusError, stack: stack_id if stack_status == 'DELETE_FAILED'
65
+ sleep retry_interval
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,13 +1,15 @@
1
+ require 'vagrant-openstack-provider/action/abstract_action'
2
+
1
3
  module VagrantPlugins
2
4
  module Openstack
3
5
  module Action
4
- class Message
6
+ class Message < AbstractAction
5
7
  def initialize(app, _env, message)
6
8
  @app = app
7
9
  @message = message
8
10
  end
9
11
 
10
- def call(env)
12
+ def execute(env)
11
13
  env[:ui].info(@message)
12
14
  @app.call(env)
13
15
  end
@@ -2,13 +2,15 @@ require 'log4r'
2
2
 
3
3
  require 'vagrant-openstack-provider/config_resolver'
4
4
  require 'vagrant-openstack-provider/utils'
5
+ require 'vagrant-openstack-provider/action/abstract_action'
5
6
 
6
7
  module VagrantPlugins
7
8
  module Openstack
8
9
  module Action
9
10
  # This action reads the SSH info for the machine and puts it into the
10
11
  # `:machine_ssh_info` key in the environment.
11
- class ReadSSHInfo
12
+
13
+ class ReadSSHInfo < AbstractAction
12
14
  def initialize(app, _env, resolver = ConfigResolver.new, utils = Utils.new)
13
15
  @app = app
14
16
  @logger = Log4r::Logger.new('vagrant_openstack::action::read_ssh_info')
@@ -16,7 +18,7 @@ module VagrantPlugins
16
18
  @utils = utils
17
19
  end
18
20
 
19
- def call(env)
21
+ def execute(env)
20
22
  @logger.info 'Reading SSH info'
21
23
  server_id = env[:machine].id.to_sym
22
24
  SSHInfoHolder.instance.tap do |holder|
@@ -1,17 +1,19 @@
1
1
  require 'log4r'
2
2
 
3
+ require 'vagrant-openstack-provider/action/abstract_action'
4
+
3
5
  module VagrantPlugins
4
6
  module Openstack
5
7
  module Action
6
8
  # This action reads the state of the machine and puts it in the
7
9
  # `:machine_state_id` key in the environment.
8
- class ReadState
10
+ class ReadState < AbstractAction
9
11
  def initialize(app, _env)
10
12
  @app = app
11
13
  @logger = Log4r::Logger.new('vagrant_openstack::action::read_state')
12
14
  end
13
15
 
14
- def call(env)
16
+ def execute(env)
15
17
  env[:machine_state_id] = read_state(env)
16
18
  @app.call(env)
17
19
  end
@@ -29,8 +31,11 @@ module VagrantPlugins
29
31
  return :not_created
30
32
  end
31
33
 
32
- # Return the state
33
- server['status'].downcase.to_sym
34
+ if !server['OS-EXT-STS:task_state'].nil?
35
+ server['OS-EXT-STS:task_state'].downcase.to_sym
36
+ else
37
+ server['status'].downcase.to_sym
38
+ end
34
39
  end
35
40
  end
36
41
  end
@@ -1,13 +1,15 @@
1
+ require 'vagrant-openstack-provider/action/abstract_action'
2
+
1
3
  module VagrantPlugins
2
4
  module Openstack
3
5
  module Action
4
- class Resume
6
+ class Resume < AbstractAction
5
7
  def initialize(app, _env)
6
8
  @app = app
7
9
  @logger = Log4r::Logger.new('vagrant_openstack::action::resume_server')
8
10
  end
9
11
 
10
- def call(env)
12
+ def execute(env)
11
13
  if env[:machine].id
12
14
  @logger.info "Resuming suspended VM #{env[:machine].id}..."
13
15
  env[:ui].info I18n.t('vagrant.actions.vm.resume.resuming')
@@ -1,15 +1,17 @@
1
1
  require 'log4r'
2
2
 
3
+ require 'vagrant-openstack-provider/action/abstract_action'
4
+
3
5
  module VagrantPlugins
4
6
  module Openstack
5
7
  module Action
6
- class StartServer
8
+ class StartServer < AbstractAction
7
9
  def initialize(app, _env)
8
10
  @app = app
9
11
  @logger = Log4r::Logger.new('vagrant_openstack::action::start_server')
10
12
  end
11
13
 
12
- def call(env)
14
+ def execute(env)
13
15
  if env[:machine].id
14
16
  env[:ui].info(I18n.t('vagrant_openstack.starting_server'))
15
17
  env[:openstack_client].nova.start_server(env, env[:machine].id)
@@ -1,15 +1,17 @@
1
1
  require 'log4r'
2
2
 
3
+ require 'vagrant-openstack-provider/action/abstract_action'
4
+
3
5
  module VagrantPlugins
4
6
  module Openstack
5
7
  module Action
6
- class StopServer
8
+ class StopServer < AbstractAction
7
9
  def initialize(app, _env)
8
10
  @app = app
9
11
  @logger = Log4r::Logger.new('vagrant_openstack::action::stop_server')
10
12
  end
11
13
 
12
- def call(env)
14
+ def execute(env)
13
15
  if env[:machine].id
14
16
  @logger.info "Stopping server #{env[:machine].id}..."
15
17
  env[:ui].info(I18n.t('vagrant_openstack.stopping_server'))
@@ -1,13 +1,15 @@
1
+ require 'vagrant-openstack-provider/action/abstract_action'
2
+
1
3
  module VagrantPlugins
2
4
  module Openstack
3
5
  module Action
4
- class Suspend
6
+ class Suspend < AbstractAction
5
7
  def initialize(app, _env)
6
8
  @app = app
7
9
  @logger = Log4r::Logger.new('vagrant_openstack::action::suspend_server')
8
10
  end
9
11
 
10
- def call(env)
12
+ def execute(env)
11
13
  if env[:machine].id
12
14
  @logger.info "Saving VM #{env[:machine].id} state and suspending execution..."
13
15
  env[:ui].info I18n.t('vagrant.actions.vm.suspend.suspending')
@@ -2,19 +2,20 @@ require 'log4r'
2
2
  require 'rbconfig'
3
3
  require 'vagrant/util/subprocess'
4
4
 
5
+ require 'vagrant-openstack-provider/action/abstract_action'
6
+
5
7
  module VagrantPlugins
6
8
  module Openstack
7
9
  module Action
8
- class SyncFolders
10
+ class SyncFolders < AbstractAction
9
11
  def initialize(app, _env)
10
12
  @app = app
11
13
  end
12
14
 
13
- def call(env)
15
+ def execute(env)
14
16
  sync_method = env[:machine].provider_config.sync_method
15
- ssh_disabled = env[:machine].provider_config.ssh_disabled
16
- if sync_method == 'none' || ssh_disabled
17
- NoSyncFolders.new(@app, env, ssh_disabled).call(env)
17
+ if sync_method == 'none'
18
+ NoSyncFolders.new(@app, env).call(env)
18
19
  elsif sync_method == 'rsync'
19
20
  RsyncFolders.new(@app, env).call(env)
20
21
  else
@@ -24,15 +25,13 @@ module VagrantPlugins
24
25
  end
25
26
 
26
27
  class NoSyncFolders
27
- def initialize(app, _env, ssh_disabled)
28
+ def initialize(app, _env)
28
29
  @app = app
29
- @ssh_disabled = ssh_disabled
30
30
  end
31
31
 
32
32
  def call(env)
33
33
  @app.call(env)
34
- env[:ui].info('Folders will not be synced because provider config ssh_disabled is set to true') if @ssh_disabled
35
- env[:ui].info('Sync folders are disabled in the provider configuration') unless @ssh_disabled
34
+ env[:ui].info(I18n.t('vagrant_openstack.disabled_sync_folders'))
36
35
  end
37
36
  end
38
37
 
@@ -48,6 +47,11 @@ module VagrantPlugins
48
47
  def call(env)
49
48
  @app.call(env)
50
49
 
50
+ if env[:machine].provider_config.ssh_disabled
51
+ env[:ui].info(I18n.t('vagrant_openstack.ssh_disabled_sync_folders'))
52
+ return
53
+ end
54
+
51
55
  ssh_info = env[:machine].ssh_info
52
56
 
53
57
  config = env[:machine].provider_config
@@ -93,14 +97,14 @@ module VagrantPlugins
93
97
  "#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
94
98
  command.compact!
95
99
 
96
- # during rsync, ignore files specified in .hgignore and
97
- # .gitignore traditional .gitignore or .hgignore files
98
- ignore_files = ['.hgignore', '.gitignore']
100
+ # during rsync, ignore files specified in list of files containing exclude patterns
101
+ # ex: rsync_ignore_files = ['.hgignore', '.gitignore']
102
+ ignore_files = []
103
+ ignore_files = env[:machine].provider_config.rsync_ignore_files unless env[:machine].provider_config.rsync_ignore_files.nil?
99
104
  ignore_files.each do |ignore_file|
100
105
  abs_ignore_file = env[:root_path].to_s + '/' + ignore_file
101
106
  command += ['--exclude-from', abs_ignore_file] if File.exist?(abs_ignore_file)
102
107
  end
103
-
104
108
  r = Vagrant::Util::Subprocess.execute(*command)
105
109
  next if r.exit_code == 0
106
110
  fail Errors::RsyncError, guestpath: guestpath, hostpath: hostpath, stderr: r.stderr
@@ -3,7 +3,7 @@ require 'log4r'
3
3
  module VagrantPlugins
4
4
  module Openstack
5
5
  module Action
6
- class WaitForServerToBeAccessible
6
+ class WaitForServerToBeAccessible < AbstractAction
7
7
  def initialize(app, env, resolver = nil, ssh = nil)
8
8
  @logger = Log4r::Logger.new('vagrant_openstack::action::wait_accessible')
9
9
  @app = app
@@ -11,7 +11,7 @@ module VagrantPlugins
11
11
  @resolver = resolver || VagrantPlugins::Openstack::ConfigResolver.new
12
12
  end
13
13
 
14
- def call(env)
14
+ def execute(env)
15
15
  waiting_for_server_to_be_reachable(env)
16
16
  @logger.info 'The server is ready'
17
17
  env[:ui].info(I18n.t('vagrant_openstack.ready'))
@@ -41,6 +41,9 @@ module VagrantPlugins
41
41
  end
42
42
 
43
43
  env[:ssh_run_command] = 'exit 0'
44
+ env[:ssh_opts] = {
45
+ extra_args: ['-o', 'BatchMode=yes']
46
+ }
44
47
  @ssh.call(env)
45
48
  return true if env[:ssh_run_exit_status] == 0
46
49
 
@@ -1,10 +1,12 @@
1
1
  require 'log4r'
2
2
  require 'timeout'
3
3
 
4
+ require 'vagrant-openstack-provider/action/abstract_action'
5
+
4
6
  module VagrantPlugins
5
7
  module Openstack
6
8
  module Action
7
- class WaitForServerToBeActive
9
+ class WaitForServerToBeActive < AbstractAction
8
10
  def initialize(app, _env, retry_interval = 3, timeout = 200)
9
11
  @app = app
10
12
  @logger = Log4r::Logger.new('vagrant_openstack::action::start_server')
@@ -12,11 +14,11 @@ module VagrantPlugins
12
14
  @timeout = timeout
13
15
  end
14
16
 
15
- def call(env)
17
+ def execute(env)
16
18
  if env[:machine].id
17
19
  env[:ui].info(I18n.t('vagrant_openstack.waiting_start'))
18
20
  client = env[:openstack_client].nova
19
- timeout(@timeout) do
21
+ timeout(@timeout, Errors::Timeout) do
20
22
  while client.get_server_details(env, env[:machine].id)['status'] != 'ACTIVE'
21
23
  sleep @retry_interval
22
24
  @logger.info('Waiting for server to be active')
@@ -1,10 +1,12 @@
1
1
  require 'log4r'
2
2
  require 'timeout'
3
3
 
4
+ require 'vagrant-openstack-provider/action/abstract_action'
5
+
4
6
  module VagrantPlugins
5
7
  module Openstack
6
8
  module Action
7
- class WaitForServerToStop
9
+ class WaitForServerToStop < AbstractAction
8
10
  def initialize(app, _env, retry_interval = 3, timeout = 200)
9
11
  @app = app
10
12
  @logger = Log4r::Logger.new('vagrant_openstack::action::stop_server')
@@ -12,11 +14,11 @@ module VagrantPlugins
12
14
  @timeout = timeout
13
15
  end
14
16
 
15
- def call(env)
17
+ def execute(env)
16
18
  if env[:machine].id
17
19
  env[:ui].info(I18n.t('vagrant_openstack.waiting_stop'))
18
20
  client = env[:openstack_client].nova
19
- timeout(@timeout) do
21
+ timeout(@timeout, Errors::Timeout) do
20
22
  while client.get_server_details(env, env[:machine].id)['status'] != 'SHUTOFF'
21
23
  sleep @retry_interval
22
24
  @logger.info('Waiting for server to stop')
@@ -0,0 +1,66 @@
1
+ module VagrantPlugins
2
+ module Openstack
3
+ module Catalog
4
+ class OpenstackCatalog
5
+ def initialize
6
+ @logger = Log4r::Logger.new('vagrant_openstack::action::openstack_reader')
7
+ end
8
+
9
+ def read(env, catalog)
10
+ config = env[:machine].provider_config
11
+ client = env[:openstack_client]
12
+ endpoints = client.session.endpoints
13
+ @logger.info(I18n.t('vagrant_openstack.client.looking_for_available_endpoints'))
14
+ @logger.info("Selecting endpoints matching region '#{config.region}'") unless config.region.nil?
15
+
16
+ catalog.each do |service|
17
+ se = service['endpoints']
18
+ if config.region.nil?
19
+ if se.size > 1
20
+ env[:ui].warn I18n.t('vagrant_openstack.client.multiple_endpoint', size: se.size, type: service['type'])
21
+ env[:ui].warn " => #{service['endpoints'][0]['publicURL']}"
22
+ end
23
+ url = se[0]['publicURL'].strip
24
+ else
25
+ se.each do |endpoint|
26
+ url = endpoint['publicURL'].strip if endpoint['region'].eql? config.region
27
+ end
28
+ end
29
+ endpoints[service['type'].to_sym] = url unless url.nil? || url.empty?
30
+ end
31
+
32
+ endpoints[:network] = choose_api_version('Neutron', 'openstack_network_url', 'v2') do
33
+ client.neutron.get_api_version_list(:network)
34
+ end if config.openstack_network_url.nil? && !endpoints[:network].nil?
35
+
36
+ endpoints[:image] = choose_api_version('Glance', 'openstack_image_url', nil, false) do
37
+ client.glance.get_api_version_list(:image)
38
+ end if config.openstack_image_url.nil? && !endpoints[:image].nil?
39
+ end
40
+
41
+ private
42
+
43
+ def choose_api_version(service_name, url_property, version_prefix = nil, fail_if_not_found = true)
44
+ versions = yield
45
+
46
+ return versions.first['links'].first['href'] if version_prefix.nil?
47
+
48
+ if versions.size == 1
49
+ return versions.first['links'].first['href'] if versions.first['id'].start_with?(version_prefix)
50
+ fail Errors::NoMatchingApiVersion, api_name: service_name, url_property: url_property, version_list: version_list if fail_if_not_found
51
+ end
52
+
53
+ version_list = ''
54
+ versions.each do |version|
55
+ return version['links'].first['href'] if version['id'].start_with?(version_prefix)
56
+ links = version['links'].map { |l| l['href'] }
57
+ version_list << "#{version['id'].ljust(6)} #{version['status'].ljust(10)} #{links}\n"
58
+ end
59
+
60
+ fail Errors::NoMatchingApiVersion, api_name: service_name, url_property: url_property, version_list: version_list if fail_if_not_found
61
+ nil
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end