vagrant-openstack-provider 0.1.2 → 0.2.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 (57) hide show
  1. checksums.yaml +13 -5
  2. data/.rubocop.yml +28 -0
  3. data/Appraisals +3 -3
  4. data/CHANGELOG.md +4 -0
  5. data/Gemfile +3 -0
  6. data/Rakefile +6 -2
  7. data/Vagrantfile +4 -15
  8. data/gemfiles/latest_stable.gemfile +2 -0
  9. data/gemfiles/oldest_current.gemfile +2 -0
  10. data/gemfiles/previous_release.gemfile +2 -0
  11. data/lib/vagrant-openstack-provider.rb +18 -13
  12. data/lib/vagrant-openstack-provider/action.rb +112 -46
  13. data/lib/vagrant-openstack-provider/action/connect_openstack.rb +9 -10
  14. data/lib/vagrant-openstack-provider/action/create_server.rb +86 -57
  15. data/lib/vagrant-openstack-provider/action/delete_server.rb +5 -6
  16. data/lib/vagrant-openstack-provider/action/{is_created.rb → message.rb} +4 -3
  17. data/lib/vagrant-openstack-provider/action/read_ssh_info.rb +7 -27
  18. data/lib/vagrant-openstack-provider/action/read_state.rb +7 -9
  19. data/lib/vagrant-openstack-provider/action/resume.rb +20 -0
  20. data/lib/vagrant-openstack-provider/action/start_server.rb +22 -0
  21. data/lib/vagrant-openstack-provider/action/stop_server.rb +22 -0
  22. data/lib/vagrant-openstack-provider/action/suspend.rb +20 -0
  23. data/lib/vagrant-openstack-provider/action/sync_folders.rb +27 -38
  24. data/lib/vagrant-openstack-provider/action/wait_stop.rb +29 -0
  25. data/lib/vagrant-openstack-provider/client/keystone.rb +76 -0
  26. data/lib/vagrant-openstack-provider/client/neutron.rb +32 -0
  27. data/lib/vagrant-openstack-provider/client/nova.rb +166 -0
  28. data/lib/vagrant-openstack-provider/client/openstack.rb +41 -0
  29. data/lib/vagrant-openstack-provider/client/utils.rb +38 -0
  30. data/lib/vagrant-openstack-provider/config.rb +38 -110
  31. data/lib/vagrant-openstack-provider/errors.rb +7 -3
  32. data/lib/vagrant-openstack-provider/plugin.rb +8 -8
  33. data/lib/vagrant-openstack-provider/provider.rb +6 -6
  34. data/lib/vagrant-openstack-provider/version.rb +1 -1
  35. data/locales/en.yml +83 -5
  36. data/numergyrc +22 -0
  37. data/spec/vagrant-openstack-provider/action/create_server_spec.rb +89 -0
  38. data/spec/vagrant-openstack-provider/client/keystone_spec.rb +140 -0
  39. data/spec/vagrant-openstack-provider/client/neutron_spec.rb +53 -0
  40. data/spec/vagrant-openstack-provider/client/nova_spec.rb +373 -0
  41. data/spec/vagrant-openstack-provider/client/utils_spec.rb +125 -0
  42. data/spec/vagrant-openstack-provider/config_spec.rb +117 -0
  43. data/spec/vagrant-openstack-provider/provider_spec.rb +13 -0
  44. data/spec/vagrant-openstack-provider/spec_helper.rb +23 -0
  45. data/vagrant-openstack-provider.gemspec +13 -14
  46. metadata +40 -30
  47. data/features/provision.feature +0 -35
  48. data/features/steps/sdk_steps.rb +0 -13
  49. data/features/steps/server_steps.rb +0 -25
  50. data/features/support/env.rb +0 -37
  51. data/features/support/fog_mock.rb +0 -19
  52. data/features/vagrant-openstack-provider.feature +0 -70
  53. data/lib/vagrant-openstack-provider/action/message_already_created.rb +0 -16
  54. data/lib/vagrant-openstack-provider/action/message_not_created.rb +0 -16
  55. data/lib/vagrant-openstack-provider/openstack_client.rb +0 -98
  56. data/spec/vagrant-openstack/config_spec.rb +0 -184
  57. data/stackrc +0 -31
@@ -1,7 +1,8 @@
1
- require "log4r"
2
- require "restclient"
3
- require "json"
4
- require_relative "../openstack_client"
1
+ require 'log4r'
2
+ require 'restclient'
3
+ require 'json'
4
+
5
+ require 'vagrant-openstack-provider/client/openstack'
5
6
 
6
7
  module VagrantPlugins
7
8
  module Openstack
@@ -10,17 +11,15 @@ module VagrantPlugins
10
11
  # puts the Openstack connection object into the `:openstack_compute` key
11
12
  # in the environment.
12
13
  class ConnectOpenstack
13
- def initialize(app, env)
14
+ def initialize(app, _env)
14
15
  @app = app
15
- @logger = Log4r::Logger.new("vagrant_openstack::action::connect_openstack")
16
+ @logger = Log4r::Logger.new('vagrant_openstack::action::connect_openstack')
16
17
  end
17
18
 
18
19
  def call(env)
19
- # Get the configs
20
- config = env[:machine].provider_config
21
- client = OpenstackClient::new()
20
+ client = VagrantPlugins::Openstack
22
21
  env[:openstack_client] = client
23
- client.authenticate(env)
22
+ client.keystone.authenticate(env) if client.session.token.nil?
24
23
  @app.call(env)
25
24
  end
26
25
  end
@@ -1,6 +1,6 @@
1
- require "log4r"
1
+ require 'log4r'
2
2
  require 'socket'
3
- require "timeout"
3
+ require 'timeout'
4
4
 
5
5
  require 'vagrant/util/retryable'
6
6
 
@@ -10,108 +10,137 @@ module VagrantPlugins
10
10
  class CreateServer
11
11
  include Vagrant::Util::Retryable
12
12
 
13
- def initialize(app, env)
13
+ def initialize(app, _env)
14
14
  @app = app
15
- @logger = Log4r::Logger.new("vagrant_openstack::action::create_server")
15
+ @logger = Log4r::Logger.new('vagrant_openstack::action::create_server')
16
16
  end
17
17
 
18
18
  def call(env)
19
19
  config = env[:machine].provider_config
20
- client = env[:openstack_client]
20
+ nova = env[:openstack_client].nova
21
21
 
22
- # Find the flavor
23
- env[:ui].info(I18n.t("vagrant_openstack.finding_flavor"))
24
- flavors = client.get_all_flavors(env)
25
- flavor = find_matching(flavors, config.flavor)
26
- raise Errors::NoMatchingFlavor if !flavor
27
-
28
- # Find the image
29
- env[:ui].info(I18n.t("vagrant_openstack.finding_image"))
30
- images = client.get_all_images(env)
31
- image = find_matching(images, config.image)
32
- raise Errors::NoMatchingImage if !image
33
-
34
- # Figure out the name for the server
22
+ flavor = resolve_flavor(env)
23
+ image = resolve_image(env)
24
+ networks = resolve_networks(env)
35
25
  server_name = config.server_name || env[:machine].name
36
26
 
37
- # Output the settings we're going to use to the user
38
- env[:ui].info(I18n.t("vagrant_openstack.launching_server"))
39
- env[:ui].info(" -- Flavor : #{flavor.name}")
40
- env[:ui].info(" -- FlavorRef : #{flavor.id}")
41
- env[:ui].info(" -- Image : #{image.name}")
42
- env[:ui].info(" -- KeyPair : #{config.keypair_name}")
43
- env[:ui].info(" -- ImageRef : #{image.id}")
44
- env[:ui].info(" -- Disk Config : #{config.disk_config}") if config.disk_config
45
- env[:ui].info(" -- Network : #{config.network}") if config.network
46
- env[:ui].info(" -- Tenant : #{config.tenant_name}")
47
- env[:ui].info(" -- Name : #{server_name}")
48
-
49
- #TODO(julienvey) add metadata
50
- #TODO(julienvey) add availability_zone
51
- #TODO(julienvey) add disk_config
52
-
53
- server_id = client.create_server(env, server_name, image.id, flavor.id, config.keypair_name)
54
-
55
- #TODO(julienvey) Find a network if provided
56
- #if config.network
57
- # network = find_matching(env[:openstack_network].networks, config.network)
58
- # options[:nics] = [{"net_id" => network.id}] if network
59
- #end
27
+ env[:ui].info(I18n.t('vagrant_openstack.launching_server'))
28
+ env[:ui].info(" -- Tenant : #{config.tenant_name}")
29
+ env[:ui].info(" -- Name : #{server_name}")
30
+ env[:ui].info(" -- Flavor : #{flavor.name}")
31
+ env[:ui].info(" -- FlavorRef : #{flavor.id}")
32
+ env[:ui].info(" -- Image : #{image.name}")
33
+ env[:ui].info(" -- ImageRef : #{image.id}")
34
+ env[:ui].info(" -- KeyPair : #{config.keypair_name}")
35
+ unless networks.empty?
36
+ if networks.size == 1
37
+ env[:ui].info(" -- Network : #{config.networks[0]}")
38
+ else
39
+ env[:ui].info(" -- Networks : #{config.networks}")
40
+ end
41
+ end
42
+
43
+ server_id = nova.create_server(env, server_name, image.id, flavor.id, networks, config.keypair_name)
60
44
 
61
45
  # Store the ID right away so we can track it
62
46
  env[:machine].id = server_id
63
47
 
64
48
  # Wait for the server to finish building
65
- env[:ui].info(I18n.t("vagrant_openstack.waiting_for_build"))
49
+ env[:ui].info(I18n.t('vagrant_openstack.waiting_for_build'))
66
50
  timeout(200) do
67
- while client.get_server_details(env, server_id)['status'] != 'ACTIVE' do
51
+ while nova.get_server_details(env, server_id)['status'] != 'ACTIVE'
68
52
  sleep 3
69
- @logger.debug("Waiting for server to be ACTIVE")
53
+ @logger.debug('Waiting for server to be ACTIVE')
70
54
  end
71
55
  end
72
56
 
73
57
  if config.floating_ip
74
58
  env[:ui].info("Using floating IP #{config.floating_ip}")
75
- client.add_floating_ip(env, server_id, config.floating_ip)
59
+ nova.add_floating_ip(env, server_id, config.floating_ip)
76
60
  end
77
61
 
78
- if !env[:interrupted]
62
+ unless env[:interrupted]
79
63
  # Clear the line one more time so the progress is removed
80
64
  env[:ui].clear_line
81
65
 
82
66
  # Wait for SSH to become available
83
67
  host = env[:machine].provider_config.floating_ip
84
68
  ssh_timeout = env[:machine].provider_config.ssh_timeout
85
- sleep 240
86
- if !port_open?(env, host, 22, ssh_timeout)
87
- env[:ui].error(I18n.t("vagrant_openstack.timeout"))
88
- raise Errors::SshUnavailable,
89
- :host => host,
90
- :timeout => ssh_timeout
69
+ unless port_open?(env, host, 22, ssh_timeout)
70
+ env[:ui].error(I18n.t('vagrant_openstack.timeout'))
71
+ fail Errors::SshUnavailable, host: host, timeout: ssh_timeout
91
72
  end
92
73
 
93
- env[:ui].info(I18n.t("vagrant_openstack.ready"))
74
+ env[:ui].info(I18n.t('vagrant_openstack.ready'))
94
75
  end
95
76
 
96
77
  @app.call(env)
97
78
  end
98
79
 
99
- protected
80
+ private
81
+
82
+ def resolve_flavor(env)
83
+ config = env[:machine].provider_config
84
+ nova = env[:openstack_client].nova
85
+ env[:ui].info(I18n.t('vagrant_openstack.finding_flavor'))
86
+ flavors = nova.get_all_flavors(env)
87
+ flavor = find_matching(flavors, config.flavor)
88
+ fail Errors::NoMatchingFlavor unless flavor
89
+ flavor
90
+ end
91
+
92
+ def resolve_image(env)
93
+ config = env[:machine].provider_config
94
+ nova = env[:openstack_client].nova
95
+ env[:ui].info(I18n.t('vagrant_openstack.finding_image'))
96
+ images = nova.get_all_images(env)
97
+ image = find_matching(images, config.image)
98
+ fail Errors::NoMatchingImage unless image
99
+ image
100
+ end
101
+
102
+ def resolve_networks(env)
103
+ config = env[:machine].provider_config
104
+ return [] if config.networks.nil? || config.networks.empty?
105
+ env[:ui].info(I18n.t('vagrant_openstack.finding_networks'))
106
+
107
+ private_networks = env[:openstack_client].neutron.get_private_networks(env)
108
+ private_network_ids = private_networks.map { |n| n[:id] }
109
+
110
+ networks = []
111
+ config.networks.each do |network|
112
+ if private_network_ids.include?(network)
113
+ networks << network
114
+ next
115
+ end
116
+ net_id = nil
117
+ private_networks.each do |n| # Bad algorithm complexity, but here we don't care...
118
+ next unless n[:name].eql? network
119
+ fail "Multiple networks with name '#{n[:name]}'" unless net_id.nil?
120
+ net_id = n[:id]
121
+ end
122
+ fail "No matching network with name '#{network}'" if net_id.nil?
123
+ networks << net_id
124
+ end
125
+ networks
126
+ end
100
127
 
101
128
  def port_open?(env, ip, port, timeout)
102
129
  start_time = Time.now
103
130
  current_time = start_time
131
+ nb_retry = 0
104
132
  while (current_time - start_time) <= timeout
105
133
  begin
106
- env[:ui].info(I18n.t("vagrant_openstack.waiting_for_ssh"))
134
+ env[:ui].info(I18n.t('vagrant_openstack.waiting_for_ssh')) if nb_retry % 5 == 0
107
135
  TCPSocket.new(ip, port)
108
136
  return true
109
- rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
137
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ETIMEDOUT
138
+ nb_retry += 1
110
139
  sleep 1
111
140
  end
112
141
  current_time = Time.now
113
142
  end
114
- return false
143
+ false
115
144
  end
116
145
 
117
146
  # This method finds a matching _thing_ in a collection of
@@ -1,20 +1,19 @@
1
- require "log4r"
1
+ require 'log4r'
2
2
 
3
3
  module VagrantPlugins
4
4
  module Openstack
5
5
  module Action
6
6
  # This deletes the running server, if there is one.
7
7
  class DeleteServer
8
- def initialize(app, env)
8
+ def initialize(app, _env)
9
9
  @app = app
10
- @logger = Log4r::Logger.new("vagrant_openstack::action::delete_server")
10
+ @logger = Log4r::Logger.new('vagrant_openstack::action::delete_server')
11
11
  end
12
12
 
13
13
  def call(env)
14
14
  if env[:machine].id
15
- env[:ui].info(I18n.t("vagrant_openstack.deleting_server"))
16
- client = env[:openstack_client]
17
- client.delete_server(env, env[:machine].id)
15
+ env[:ui].info(I18n.t('vagrant_openstack.deleting_server'))
16
+ env[:openstack_client].nova.delete_server(env, env[:machine].id)
18
17
  env[:machine].id = nil
19
18
  end
20
19
 
@@ -1,13 +1,14 @@
1
1
  module VagrantPlugins
2
2
  module Openstack
3
3
  module Action
4
- class IsCreated
5
- def initialize(app, env)
4
+ class Message
5
+ def initialize(app, _env, message)
6
6
  @app = app
7
+ @message = message
7
8
  end
8
9
 
9
10
  def call(env)
10
- env[:result] = env[:machine].state.id != :not_created
11
+ env[:ui].info(@message)
11
12
  @app.call(env)
12
13
  end
13
14
  end
@@ -1,4 +1,4 @@
1
- require "log4r"
1
+ require 'log4r'
2
2
 
3
3
  module VagrantPlugins
4
4
  module Openstack
@@ -6,9 +6,9 @@ module VagrantPlugins
6
6
  # This action reads the SSH info for the machine and puts it into the
7
7
  # `:machine_ssh_info` key in the environment.
8
8
  class ReadSSHInfo
9
- def initialize(app, env)
9
+ def initialize(app, _env)
10
10
  @app = app
11
- @logger = Log4r::Logger.new("vagrant_openstack::action::read_ssh_info")
11
+ @logger = Log4r::Logger.new('vagrant_openstack::action::read_ssh_info')
12
12
  end
13
13
 
14
14
  def call(env)
@@ -18,32 +18,12 @@ module VagrantPlugins
18
18
  end
19
19
 
20
20
  def read_ssh_info(env)
21
- client = env[:openstack_client]
22
- machine = env[:machine]
23
21
  config = env[:machine].provider_config
24
- @logger.debug(config)
25
- return nil if machine.id.nil?
26
- begin
27
- details = client.get_server_details(env, machine.id)
28
- rescue Exception => e
29
- # The machine can't be found
30
- @logger.error(e)
31
- @logger.info("Machine couldn't be found, assuming it got destroyed.")
32
- machine.id = nil
33
- return nil
34
- end
35
-
36
- for addr in details['addresses']['private']
37
- if addr['OS-EXT-IPS:type'] == 'floating'
38
- host = addr['addr']
39
- end
40
- end
41
-
42
- return {
22
+ {
43
23
  # Usually there should only be one public IP
44
- :host => host,
45
- :port => 22,
46
- :username => config.ssh_username
24
+ host: config.floating_ip,
25
+ port: 22,
26
+ username: config.ssh_username
47
27
  }
48
28
  end
49
29
  end
@@ -1,4 +1,4 @@
1
- require "log4r"
1
+ require 'log4r'
2
2
 
3
3
  module VagrantPlugins
4
4
  module Openstack
@@ -6,33 +6,31 @@ module VagrantPlugins
6
6
  # This action reads the state of the machine and puts it in the
7
7
  # `:machine_state_id` key in the environment.
8
8
  class ReadState
9
- def initialize(app, env)
9
+ def initialize(app, _env)
10
10
  @app = app
11
- @logger = Log4r::Logger.new("vagrant_openstack::action::read_state")
11
+ @logger = Log4r::Logger.new('vagrant_openstack::action::read_state')
12
12
  end
13
13
 
14
14
  def call(env)
15
15
  env[:machine_state_id] = read_state(env)
16
-
17
16
  @app.call(env)
18
17
  end
19
18
 
20
19
  def read_state(env)
21
20
  machine = env[:machine]
22
- client = env[:openstack_client]
23
21
  return :not_created if machine.id.nil?
24
22
 
25
23
  # Find the machine
26
- server = client.get_server_details(env, machine.id)
27
- if server.nil? || server['status'] == "DELETED"
24
+ server = env[:openstack_client].nova.get_server_details(env, machine.id)
25
+ if server.nil? || server['status'] == 'DELETED'
28
26
  # The machine can't be found
29
- @logger.info("Machine not found or deleted, assuming it got destroyed.")
27
+ @logger.info('Machine not found or deleted, assuming it got destroyed.')
30
28
  machine.id = nil
31
29
  return :not_created
32
30
  end
33
31
 
34
32
  # Return the state
35
- return server['status'].downcase.to_sym
33
+ server['status'].downcase.to_sym
36
34
  end
37
35
  end
38
36
  end
@@ -0,0 +1,20 @@
1
+ module VagrantPlugins
2
+ module Openstack
3
+ module Action
4
+ class Resume
5
+ def initialize(app, _env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ if env[:machine].id
11
+ env[:ui].info I18n.t('vagrant.actions.vm.resume.resuming')
12
+ env[:openstack_client].nova.resume_server(env, env[:machine].id)
13
+ end
14
+
15
+ @app.call(env)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require 'log4r'
2
+
3
+ module VagrantPlugins
4
+ module Openstack
5
+ module Action
6
+ class StartServer
7
+ def initialize(app, _env)
8
+ @app = app
9
+ @logger = Log4r::Logger.new('vagrant_openstack::action::start_server')
10
+ end
11
+
12
+ def call(env)
13
+ if env[:machine].id
14
+ env[:ui].info(I18n.t('vagrant_openstack.starting_server'))
15
+ env[:openstack_client].nova.start_server(env, env[:machine].id)
16
+ end
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require 'log4r'
2
+
3
+ module VagrantPlugins
4
+ module Openstack
5
+ module Action
6
+ class StopServer
7
+ def initialize(app, _env)
8
+ @app = app
9
+ @logger = Log4r::Logger.new('vagrant_openstack::action::stop_server')
10
+ end
11
+
12
+ def call(env)
13
+ if env[:machine].id
14
+ env[:ui].info(I18n.t('vagrant_openstack.stopping_server'))
15
+ env[:openstack_client].nova.stop_server(env, env[:machine].id)
16
+ end
17
+ @app.call(env)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end