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
@@ -4,10 +4,12 @@ module VagrantPlugins
4
4
  class Resume
5
5
  def initialize(app, _env)
6
6
  @app = app
7
+ @logger = Log4r::Logger.new('vagrant_openstack::action::resume_server')
7
8
  end
8
9
 
9
10
  def call(env)
10
11
  if env[:machine].id
12
+ @logger.info "Resuming suspended VM #{env[:machine].id}..."
11
13
  env[:ui].info I18n.t('vagrant.actions.vm.resume.resuming')
12
14
  env[:openstack_client].nova.resume_server(env, env[:machine].id)
13
15
  end
@@ -11,6 +11,7 @@ module VagrantPlugins
11
11
 
12
12
  def call(env)
13
13
  if env[:machine].id
14
+ @logger.info "Stopping server #{env[:machine].id}..."
14
15
  env[:ui].info(I18n.t('vagrant_openstack.stopping_server'))
15
16
  env[:openstack_client].nova.stop_server(env, env[:machine].id)
16
17
  end
@@ -4,10 +4,12 @@ module VagrantPlugins
4
4
  class Suspend
5
5
  def initialize(app, _env)
6
6
  @app = app
7
+ @logger = Log4r::Logger.new('vagrant_openstack::action::suspend_server')
7
8
  end
8
9
 
9
10
  def call(env)
10
11
  if env[:machine].id
12
+ @logger.info "Saving VM #{env[:machine].id} state and suspending execution..."
11
13
  env[:ui].info I18n.t('vagrant.actions.vm.suspend.suspending')
12
14
  env[:openstack_client].nova.suspend_server(env, env[:machine].id)
13
15
  end
@@ -97,8 +97,9 @@ module VagrantPlugins
97
97
  command += ['--exclude-from', abs_ignore_file] if File.exist?(abs_ignore_file)
98
98
  end
99
99
 
100
- next if Vagrant::Util::Subprocess.execute(*command).exit_code == 0
101
- ail Errors::RsyncError, guestpath: guestpath, hostpath: hostpath, stderr: r.stderr
100
+ r = Vagrant::Util::Subprocess.execute(*command)
101
+ next if r.exit_code == 0
102
+ fail Errors::RsyncError, guestpath: guestpath, hostpath: hostpath, stderr: r.stderr
102
103
  end
103
104
  end
104
105
 
@@ -0,0 +1,29 @@
1
+ require 'log4r'
2
+ require 'timeout'
3
+
4
+ module VagrantPlugins
5
+ module Openstack
6
+ module Action
7
+ class WaitForServerToBeActive
8
+ def initialize(app, _env)
9
+ @app = app
10
+ @logger = Log4r::Logger.new('vagrant_openstack::action::start_server')
11
+ end
12
+
13
+ def call(env)
14
+ if env[:machine].id
15
+ env[:ui].info(I18n.t('vagrant_openstack.waiting_start'))
16
+ client = env[:openstack_client].nova
17
+ timeout(200) do
18
+ while client.get_server_details(env, env[:machine].id)['status'] != 'ACTIVE'
19
+ sleep 3
20
+ @logger.info('Waiting for server to be active')
21
+ end
22
+ end
23
+ end
24
+ @app.call(env)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -17,7 +17,7 @@ module VagrantPlugins
17
17
  timeout(200) do
18
18
  while client.get_server_details(env, env[:machine].id)['status'] != 'SHUTOFF'
19
19
  sleep 3
20
- @logger.debug('Waiting for server to stop')
20
+ @logger.info('Waiting for server to stop')
21
21
  end
22
22
  end
23
23
  end
@@ -0,0 +1,26 @@
1
+ require 'log4r'
2
+ require 'restclient'
3
+ require 'json'
4
+
5
+ module VagrantPlugins
6
+ module Openstack
7
+ module Domain
8
+ class Item
9
+ attr_accessor :id, :name
10
+ def initialize(id, name)
11
+ @id = id
12
+ @name = name
13
+ end
14
+ end
15
+
16
+ class FloatingIP
17
+ attr_accessor :ip, :pool, :instance_id
18
+ def initialize(ip, pool, instance_id)
19
+ @ip = ip
20
+ @pool = pool
21
+ @instance_id = instance_id
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,96 @@
1
+ require 'log4r'
2
+ require 'restclient'
3
+ require 'json'
4
+
5
+ require 'vagrant-openstack-provider/client/keystone'
6
+ require 'vagrant-openstack-provider/client/request_logger'
7
+
8
+ module VagrantPlugins
9
+ module Openstack
10
+ module HttpUtils
11
+ include VagrantPlugins::Openstack::HttpUtils::RequestLogger
12
+
13
+ def get(env, url, headers = {})
14
+ calling_method = caller[0][/`.*'/][1..-2]
15
+ @logger.debug("#{calling_method} - start")
16
+
17
+ headers.merge!('X-Auth-Token' => @session.token, :accept => :json)
18
+
19
+ log_request(:GET, url, headers)
20
+
21
+ authenticated(env) do
22
+ RestClient.get(url, headers) { |res| handle_response(res) }.tap do
23
+ @logger.debug("#{calling_method} - end")
24
+ end
25
+ end
26
+ end
27
+
28
+ def post(env, url, body = nil, headers = {})
29
+ calling_method = caller[0][/`.*'/][1..-2]
30
+ @logger.debug("#{calling_method} - start")
31
+
32
+ headers.merge!('X-Auth-Token' => @session.token, :accept => :json, :content_type => :json)
33
+
34
+ log_request(:POST, url, body, headers)
35
+
36
+ authenticated(env) do
37
+ RestClient.post(url, body, headers) { |res| handle_response(res) }.tap do
38
+ @logger.debug("#{calling_method} - end")
39
+ end
40
+ end
41
+ end
42
+
43
+ def delete(env, url, headers = {})
44
+ calling_method = caller[0][/`.*'/][1..-2]
45
+ @logger.debug("#{calling_method} - start")
46
+
47
+ headers.merge!('X-Auth-Token' => @session.token, :accept => :json, :content_type => :json)
48
+
49
+ log_request(:DELETE, url, headers)
50
+
51
+ authenticated(env) do
52
+ RestClient.delete(url, headers) { |res| handle_response(res) }.tap do
53
+ @logger.debug("#{calling_method} - end")
54
+ end
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ ERRORS =
61
+ {
62
+ '400' => 'badRequest',
63
+ '404' => 'itemNotFound',
64
+ '409' => 'conflictingRequest'
65
+ }
66
+
67
+ def handle_response(response)
68
+ log_response(response)
69
+ case response.code
70
+ when 200, 201, 202, 204
71
+ response
72
+ when 401
73
+ fail Errors::AuthenticationRequired
74
+ when 400, 404, 409
75
+ fail Errors::VagrantOpenstackError, message: JSON.parse(response.to_s)[ERRORS[response.code.to_s]]['message']
76
+ else
77
+ fail Errors::VagrantOpenstackError, message: response.to_s
78
+ end
79
+ end
80
+
81
+ def authenticated(env)
82
+ nb_retry = 0
83
+ begin
84
+ return yield
85
+ rescue Errors::AuthenticationRequired => e
86
+ nb_retry += 1
87
+ env[:ui].warn(e)
88
+ env[:ui].warn(I18n.t('vagrant_openstack.trying_authentication'))
89
+ env[:openstack_client].keystone.authenticate(env)
90
+ retry if nb_retry < 3
91
+ raise e
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -2,10 +2,13 @@ require 'log4r'
2
2
  require 'restclient'
3
3
  require 'json'
4
4
 
5
+ require 'vagrant-openstack-provider/client/request_logger'
6
+
5
7
  module VagrantPlugins
6
8
  module Openstack
7
9
  class KeystoneClient
8
10
  include Singleton
11
+ include VagrantPlugins::Openstack::HttpUtils::RequestLogger
9
12
 
10
13
  def initialize
11
14
  @logger = Log4r::Logger.new('vagrant_openstack::keystone')
@@ -13,63 +16,49 @@ module VagrantPlugins
13
16
  end
14
17
 
15
18
  def authenticate(env)
16
- @logger.debug('Authenticating on Keystone')
19
+ @logger.info('Authenticating on Keystone')
17
20
  config = env[:machine].provider_config
18
- env[:ui].info(I18n.t('vagrant_openstack.client.authentication', project: config.tenant_name, user: config.username))
21
+ @logger.info(I18n.t('vagrant_openstack.client.authentication', project: config.tenant_name, user: config.username))
19
22
 
20
- authentication = RestClient.post(
21
- config.openstack_auth_url,
22
- {
23
- auth:
23
+ post_body =
24
+ {
25
+ auth:
24
26
  {
25
27
  tenantName: config.tenant_name,
26
28
  passwordCredentials:
27
29
  {
28
30
  username: config.username,
29
- password: config.password
31
+ password: '****'
30
32
  }
31
33
  }
32
- }.to_json,
33
- content_type: :json,
34
- accept: :json)
35
-
36
- access = JSON.parse(authentication)['access']
37
-
38
- read_endpoint_catalog(env, access['serviceCatalog'])
39
- override_endpoint_catalog_with_user_config(env)
40
- print_endpoint_catalog(env)
41
-
42
- response_token = access['token']
43
- @session.token = response_token['id']
44
- @session.project_id = response_token['tenant']['id']
45
- end
34
+ }
46
35
 
47
- private
36
+ log_request(:POST, config.openstack_auth_url, post_body.to_json)
48
37
 
49
- def read_endpoint_catalog(env, catalog)
50
- env[:ui].info(I18n.t('vagrant_openstack.client.looking_for_available_endpoints'))
38
+ post_body[:auth][:passwordCredentials][:password] = config.password
51
39
 
52
- catalog.each do |service|
53
- se = service['endpoints']
54
- if se.size > 1
55
- env[:ui].warn I18n.t('vagrant_openstack.client.multiple_endpoint', size: se.size, type: service['type'])
56
- env[:ui].warn " => #{service['endpoints'][0]['publicURL']}"
40
+ authentication = RestClient.post(config.openstack_auth_url, post_body.to_json,
41
+ content_type: :json,
42
+ accept: :json) do |response|
43
+ log_response(response)
44
+ case response.code
45
+ when 200
46
+ response
47
+ when 401
48
+ fail Errors::AuthenticationFailed
49
+ when 404
50
+ fail Errors::BadAuthenticationEndpoint
51
+ else
52
+ fail Errors::VagrantOpenstackError, message: response.to_s
57
53
  end
58
- url = se[0]['publicURL'].strip
59
- @session.endpoints[service['type'].to_sym] = url unless url.empty?
60
54
  end
61
- end
62
55
 
63
- def override_endpoint_catalog_with_user_config(env)
64
- config = env[:machine].provider_config
65
- @session.endpoints[:compute] = config.openstack_compute_url unless config.openstack_compute_url.nil?
66
- @session.endpoints[:network] = config.openstack_network_url unless config.openstack_network_url.nil?
67
- end
56
+ access = JSON.parse(authentication)['access']
57
+ response_token = access['token']
58
+ @session.token = response_token['id']
59
+ @session.project_id = response_token['tenant']['id']
68
60
 
69
- def print_endpoint_catalog(env)
70
- @session.endpoints.each do |key, value|
71
- env[:ui].info(" -- #{key.to_s.ljust 15}: #{value}")
72
- end
61
+ access['serviceCatalog']
73
62
  end
74
63
  end
75
64
  end
@@ -2,30 +2,43 @@ require 'log4r'
2
2
  require 'restclient'
3
3
  require 'json'
4
4
 
5
- require 'vagrant-openstack-provider/client/utils'
5
+ require 'vagrant-openstack-provider/client/http_utils'
6
+ require 'vagrant-openstack-provider/client/domain'
6
7
 
7
8
  module VagrantPlugins
8
9
  module Openstack
9
10
  class NeutronClient
10
11
  include Singleton
11
- include VagrantPlugins::Openstack::Utils
12
+ include VagrantPlugins::Openstack::HttpUtils
13
+ include VagrantPlugins::Openstack::Domain
12
14
 
13
15
  def initialize
14
16
  @logger = Log4r::Logger.new('vagrant_openstack::neutron')
15
17
  @session = VagrantPlugins::Openstack.session
16
18
  end
17
19
 
18
- def get_private_networks(env)
19
- authenticated(env) do
20
- networks_json = RestClient.get("#{@session.endpoints[:network]}/networks",
21
- 'X-Auth-Token' => @session.token,
22
- :accept => :json) { |res| handle_response(res) }
23
- networks = []
24
- JSON.parse(networks_json)['networks'].each do |n|
25
- networks << { id: n['id'], name: n['name'] } if n['tenant_id'].eql? @session.project_id
20
+ def get_api_version_list(_env)
21
+ json = RestClient.get(@session.endpoints[:network], 'X-Auth-Token' => @session.token, :accept => :json) do |response|
22
+ log_response(response)
23
+ case response.code
24
+ when 200, 300
25
+ response
26
+ when 401
27
+ fail Errors::AuthenticationFailed
28
+ else
29
+ fail Errors::VagrantOpenstackError, message: response.to_s
26
30
  end
27
- networks
28
31
  end
32
+ JSON.parse(json)['versions']
33
+ end
34
+
35
+ def get_private_networks(env)
36
+ networks_json = get(env, "#{@session.endpoints[:network]}/networks")
37
+ networks = []
38
+ JSON.parse(networks_json)['networks'].each do |n|
39
+ networks << Item.new(n['id'], n['name']) if n['tenant_id'].eql? @session.project_id
40
+ end
41
+ networks
29
42
  end
30
43
  end
31
44
  end
@@ -2,13 +2,15 @@ require 'log4r'
2
2
  require 'restclient'
3
3
  require 'json'
4
4
 
5
- require 'vagrant-openstack-provider/client/utils'
5
+ require 'vagrant-openstack-provider/client/http_utils'
6
+ require 'vagrant-openstack-provider/client/domain'
6
7
 
7
8
  module VagrantPlugins
8
9
  module Openstack
9
10
  class NovaClient
10
11
  include Singleton
11
- include VagrantPlugins::Openstack::Utils
12
+ include VagrantPlugins::Openstack::HttpUtils
13
+ include VagrantPlugins::Openstack::Domain
12
14
 
13
15
  def initialize
14
16
  @logger = Log4r::Logger.new('vagrant_openstack::nova')
@@ -16,135 +18,136 @@ module VagrantPlugins
16
18
  end
17
19
 
18
20
  def get_all_flavors(env)
19
- authenticated(env) do
20
- flavors_json = RestClient.get("#{@session.endpoints[:compute]}/flavors",
21
- 'X-Auth-Token' => @session.token,
22
- :accept => :json) { |res| handle_response(res) }
21
+ flavors_json = get(env, "#{@session.endpoints[:compute]}/flavors")
22
+ JSON.parse(flavors_json)['flavors'].map { |fl| Item.new(fl['id'], fl['name']) }
23
+ end
23
24
 
24
- return JSON.parse(flavors_json)['flavors'].map { |fl| Item.new(fl['id'], fl['name']) }
25
- end
25
+ def get_all_floating_ips(env)
26
+ ips_json = get(env, "#{@session.endpoints[:compute]}/os-floating-ips",
27
+ 'X-Auth-Token' => @session.token,
28
+ :accept => :json) { |res| handle_response(res) }
29
+ JSON.parse(ips_json)['floating_ips'].map { |n| FloatingIP.new(n['ip'], n['pool'], n['instance_id']) }
26
30
  end
27
31
 
28
- def get_all_images(env)
29
- authenticated(env) do
30
- images_json = RestClient.get(
31
- "#{@session.endpoints[:compute]}/images",
32
- 'X-Auth-Token' => @session.token, :accept => :json) { |res| handle_response(res) }
32
+ def allocate_floating_ip(env, pool)
33
+ ips_json = post(env, "#{@session.endpoints[:compute]}/os-floating-ips",
34
+ {
35
+ pool: pool
36
+ }.to_json,
37
+ 'X-Auth-Token' => @session.token,
38
+ :accept => :json,
39
+ :content_type => :json) { |res| handle_response(res) }
40
+ floating_ip = JSON.parse(ips_json)['floating_ip']
41
+ FloatingIP.new(floating_ip['ip'], floating_ip['pool'], floating_ip['instance_id'])
42
+ end
33
43
 
34
- JSON.parse(images_json)['images'].map { |im| Item.new(im['id'], im['name']) }
35
- end
44
+ def get_all_images(env)
45
+ images_json = get(env, "#{@session.endpoints[:compute]}/images")
46
+ JSON.parse(images_json)['images'].map { |fl| Item.new(fl['id'], fl['name']) }
36
47
  end
37
48
 
38
- def create_server(env, name, image_ref, flavor_ref, networks, keypair)
39
- authenticated(env) do
40
- server = {}.tap do |s|
41
- s['name'] = name
42
- s['imageRef'] = image_ref
43
- s['flavorRef'] = flavor_ref
44
- s['key_name'] = keypair
45
- unless networks.nil? || networks.empty?
46
- s['networks'] = []
47
- networks.each do |uuid|
48
- s['networks'] << { uuid: uuid }
49
- end
49
+ def create_server(env, options)
50
+ server = {}.tap do |s|
51
+ s['name'] = options[:name]
52
+ s['imageRef'] = options[:image_ref]
53
+ s['flavorRef'] = options[:flavor_ref]
54
+ s['key_name'] = options[:keypair]
55
+ s['availability_zone'] = options[:availability_zone] unless options[:availability_zone].nil?
56
+ unless options[:networks].nil? || options[:networks].empty?
57
+ s['networks'] = []
58
+ options[:networks].each do |uuid|
59
+ s['networks'] << { uuid: uuid }
50
60
  end
51
61
  end
52
-
53
- server = RestClient.post(
54
- "#{@session.endpoints[:compute]}/servers", { server: server }.to_json,
55
- 'X-Auth-Token' => @session.token,
56
- :accept => :json,
57
- :content_type => :json) { |res| handle_response(res) }
58
-
59
- JSON.parse(server)['server']['id']
60
62
  end
63
+ server = post(env, "#{@session.endpoints[:compute]}/servers", { server: server }.to_json)
64
+ JSON.parse(server)['server']['id']
61
65
  end
62
66
 
63
67
  def delete_server(env, server_id)
64
- authenticated(env) do
65
- RestClient.delete(
66
- "#{@session.endpoints[:compute]}/servers/#{server_id}",
67
- 'X-Auth-Token' => @session.token,
68
- :accept => :json) { |res| handle_response(res) }
69
- end
68
+ delete(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
70
69
  end
71
70
 
72
71
  def suspend_server(env, server_id)
73
- authenticated(env) do
74
- RestClient.post(
75
- "#{@session.endpoints[:compute]}/servers/#{server_id}/action", '{ "suspend": null }',
76
- 'X-Auth-Token' => @session.token,
77
- :accept => :json,
78
- :content_type => :json) { |res| handle_response(res) }
79
- end
72
+ change_server_state(env, server_id, :suspend)
80
73
  end
81
74
 
82
75
  def resume_server(env, server_id)
83
76
  # TODO(julienvey) check status before (if pause->unpause, if suspend->resume...)
84
- authenticated(env) do
85
- RestClient.post(
86
- "#{@session.endpoints[:compute]}/servers/#{server_id}/action", '{ "resume": null }',
87
- 'X-Auth-Token' => @session.token,
88
- :accept => :json,
89
- :content_type => :json) { |res| handle_response(res) }
90
- end
77
+ change_server_state(env, server_id, :resume)
91
78
  end
92
79
 
93
80
  def stop_server(env, server_id)
94
- authenticated(env) do
95
- RestClient.post(
96
- "#{@session.endpoints[:compute]}/servers/#{server_id}/action", '{ "os-stop": null }',
97
- 'X-Auth-Token' => @session.token,
98
- :accept => :json,
99
- :content_type => :json) { |res| handle_response(res) }
100
- end
81
+ change_server_state(env, server_id, :stop)
101
82
  end
102
83
 
103
84
  def start_server(env, server_id)
104
- authenticated(env) do
105
- RestClient.post(
106
- "#{@session.endpoints[:compute]}/servers/#{server_id}/action", '{ "os-start": null }',
107
- 'X-Auth-Token' => @session.token,
108
- :accept => :json,
109
- :content_type => :json) { |res| handle_response(res) }
110
- end
85
+ change_server_state(env, server_id, :start)
111
86
  end
112
87
 
113
88
  def get_server_details(env, server_id)
114
- authenticated(env) do
115
- server_details = RestClient.get(
116
- "#{@session.endpoints[:compute]}/servers/#{server_id}",
117
- 'X-Auth-Token' => @session.token,
118
- :accept => :json) { |res| handle_response(res) }
119
-
120
- return JSON.parse(server_details)['server']
121
- end
89
+ server_details = get(env, "#{@session.endpoints[:compute]}/servers/#{server_id}")
90
+ JSON.parse(server_details)['server']
122
91
  end
123
92
 
124
93
  def add_floating_ip(env, server_id, floating_ip)
125
- authenticated(env) do
126
- check_floating_ip(env, floating_ip)
127
- RestClient.post(
128
- "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
129
- {
130
- addFloatingIp:
131
- {
132
- address: floating_ip
133
- }
134
- }.to_json,
135
- 'X-Auth-Token' => @session.token,
136
- :accept => :json,
137
- :content_type => :json) { |res| handle_response(res) }
138
- end
94
+ check_floating_ip(env, floating_ip)
95
+
96
+ post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
97
+ { addFloatingIp: { address: floating_ip } }.to_json)
98
+ end
99
+
100
+ def import_keypair(env, public_key)
101
+ keyname = "vagrant-generated-#{Kernel.rand(36**8).to_s(36)}"
102
+
103
+ key_details = post(env, "#{@session.endpoints[:compute]}/os-keypairs",
104
+ { keypair:
105
+ {
106
+ name: keyname,
107
+ public_key: public_key
108
+ }
109
+ }.to_json)
110
+ JSON.parse(key_details)['keypair']['name']
111
+ end
112
+
113
+ def import_keypair_from_file(env, public_key_path)
114
+ fail "File specified in public_key_path #{public_key_path} doesn't exist" unless File.exist?(public_key_path)
115
+ file = File.open(public_key_path)
116
+ import_keypair(env, file.read)
117
+ end
118
+
119
+ def delete_keypair_if_vagrant(env, server_id)
120
+ keyname = get_server_details(env, server_id)['key_name']
121
+ delete(env, "#{@session.endpoints[:compute]}/os-keypairs/#{keyname}") if keyname.start_with?('vagrant-generated-')
122
+ end
123
+
124
+ def get_floating_ip_pools(env)
125
+ floating_ips = get(env, "#{@session.endpoints[:compute]}/os-floating-ip-pools")
126
+ JSON.parse(floating_ips)['floating_ip_pools']
127
+ end
128
+
129
+ def get_floating_ips(env)
130
+ floating_ips = get(env, "#{@session.endpoints[:compute]}/os-floating-ips")
131
+ JSON.parse(floating_ips)['floating_ips']
139
132
  end
140
133
 
141
134
  private
142
135
 
143
- def check_floating_ip(_env, floating_ip)
144
- ip_details = RestClient.get(
145
- "#{@session.endpoints[:compute]}/os-floating-ips",
146
- 'X-Auth-Token' => @session.token,
147
- :accept => :json) { |res| handle_response(res) }
136
+ VM_STATES =
137
+ {
138
+ suspend: 'suspend',
139
+ resume: 'resume',
140
+ start: 'os-start',
141
+ stop: 'os-stop'
142
+ }
143
+
144
+ def change_server_state(env, server_id, new_state)
145
+ post(env, "#{@session.endpoints[:compute]}/servers/#{server_id}/action",
146
+ { :"#{VM_STATES[new_state.to_sym]}" => nil }.to_json)
147
+ end
148
+
149
+ def check_floating_ip(env, floating_ip)
150
+ ip_details = get(env, "#{@session.endpoints[:compute]}/os-floating-ips")
148
151
 
149
152
  JSON.parse(ip_details)['floating_ips'].each do |ip|
150
153
  next unless ip['ip'] == floating_ip
@@ -154,13 +157,5 @@ module VagrantPlugins
154
157
  fail "Floating IP #{floating_ip} not available for this tenant"
155
158
  end
156
159
  end
157
-
158
- class Item
159
- attr_accessor :id, :name
160
- def initialize(id, name)
161
- @id = id
162
- @name = name
163
- end
164
- end
165
160
  end
166
161
  end