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
@@ -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