vagrant-openstack-provider 0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Appraisals +13 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +22 -0
- data/RELEASE.md +15 -0
- data/Rakefile +21 -0
- data/Vagrantfile +37 -0
- data/dummy.box +0 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/features/provision.feature +35 -0
- data/features/steps/sdk_steps.rb +13 -0
- data/features/steps/server_steps.rb +25 -0
- data/features/support/env.rb +37 -0
- data/features/support/fog_mock.rb +19 -0
- data/features/vagrant-openstack.feature +70 -0
- data/gemfiles/latest_stable.gemfile +13 -0
- data/gemfiles/oldest_current.gemfile +13 -0
- data/gemfiles/previous_release.gemfile +13 -0
- data/lib/vagrant-openstack.rb +53 -0
- data/lib/vagrant-openstack/action.rb +123 -0
- data/lib/vagrant-openstack/action/connect_openstack.rb +30 -0
- data/lib/vagrant-openstack/action/create_server.rb +134 -0
- data/lib/vagrant-openstack/action/delete_server.rb +26 -0
- data/lib/vagrant-openstack/action/is_created.rb +16 -0
- data/lib/vagrant-openstack/action/message_already_created.rb +16 -0
- data/lib/vagrant-openstack/action/message_not_created.rb +16 -0
- data/lib/vagrant-openstack/action/read_ssh_info.rb +52 -0
- data/lib/vagrant-openstack/action/read_state.rb +40 -0
- data/lib/vagrant-openstack/action/sync_folders.rb +125 -0
- data/lib/vagrant-openstack/config.rb +229 -0
- data/lib/vagrant-openstack/errors.rb +36 -0
- data/lib/vagrant-openstack/openstack_client.rb +91 -0
- data/lib/vagrant-openstack/plugin.rb +37 -0
- data/lib/vagrant-openstack/provider.rb +50 -0
- data/lib/vagrant-openstack/version.rb +5 -0
- data/locales/en.yml +85 -0
- data/spec/vagrant-openstack/config_spec.rb +184 -0
- data/stackrc +32 -0
- data/vagrant-openstack.gemspec +23 -0
- metadata +135 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require 'rbconfig'
|
3
|
+
require "vagrant/util/subprocess"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module Openstack
|
7
|
+
module Action
|
8
|
+
|
9
|
+
class SyncFolders
|
10
|
+
def initialize(app, env)
|
11
|
+
@app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
sync_method = env[:machine].provider_config.sync_method
|
16
|
+
if sync_method == "rsync"
|
17
|
+
RsyncFolders.new(@app, env).call(env)
|
18
|
+
elsif sync_method == "none"
|
19
|
+
NoSyncFolders.new(@app, env).call(env)
|
20
|
+
else
|
21
|
+
raise Errors::SyncMethodError, :sync_method_value => sync_method
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class NoSyncFolders
|
28
|
+
def initialize(app, env)
|
29
|
+
@app = app
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(env)
|
33
|
+
@app.call(env)
|
34
|
+
env[:ui].info("Sync folders are disabled")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# This middleware uses `rsync` to sync the folders over to the
|
39
|
+
# remote instance.
|
40
|
+
class RsyncFolders
|
41
|
+
def initialize(app, env)
|
42
|
+
@app = app
|
43
|
+
@logger = Log4r::Logger.new("vagrant_openstack::action::sync_folders")
|
44
|
+
@host_os = RbConfig::CONFIG['host_os']
|
45
|
+
end
|
46
|
+
|
47
|
+
def call(env)
|
48
|
+
@app.call(env)
|
49
|
+
|
50
|
+
ssh_info = env[:machine].ssh_info
|
51
|
+
|
52
|
+
config = env[:machine].provider_config
|
53
|
+
rsync_includes = config.rsync_includes.to_a
|
54
|
+
|
55
|
+
env[:machine].config.vm.synced_folders.each do |id, data|
|
56
|
+
hostpath = File.expand_path(data[:hostpath], env[:root_path])
|
57
|
+
guestpath = data[:guestpath]
|
58
|
+
|
59
|
+
# Make sure there is a trailing slash on the host path to
|
60
|
+
# avoid creating an additional directory with rsync
|
61
|
+
hostpath = "#{hostpath}/" if hostpath !~ /\/$/
|
62
|
+
|
63
|
+
# If on Windows, modify the path to work with cygwin rsync
|
64
|
+
if @host_os =~ /mswin|mingw|cygwin/
|
65
|
+
hostpath = hostpath.sub(/^([A-Za-z]):\//, "/cygdrive/#{$1.downcase}/")
|
66
|
+
end
|
67
|
+
|
68
|
+
env[:ui].info(I18n.t("vagrant_openstack.rsync_folder",
|
69
|
+
:hostpath => hostpath,
|
70
|
+
:guestpath => guestpath))
|
71
|
+
|
72
|
+
# Create the guest path
|
73
|
+
env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
|
74
|
+
env[:machine].communicate.sudo(
|
75
|
+
"chown -R #{ssh_info[:username]} '#{guestpath}'")
|
76
|
+
|
77
|
+
# Generate rsync include commands
|
78
|
+
includes = rsync_includes.each_with_object([]) { |incl, incls|
|
79
|
+
incls << "--include"
|
80
|
+
incls << incl
|
81
|
+
}
|
82
|
+
|
83
|
+
# Rsync over to the guest path using the SSH info. add
|
84
|
+
# .hg/ to exclude list as that isn't covered in
|
85
|
+
# --cvs-exclude
|
86
|
+
command = [
|
87
|
+
"rsync", "--verbose", "--archive", "-z",
|
88
|
+
"--cvs-exclude",
|
89
|
+
"--exclude", ".hg/",
|
90
|
+
*includes,
|
91
|
+
"-e", "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no #{ssh_key_options(ssh_info)}",
|
92
|
+
hostpath,
|
93
|
+
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
|
94
|
+
command.compact!
|
95
|
+
|
96
|
+
# during rsync, ignore files specified in .hgignore and
|
97
|
+
# .gitignore traditional .gitignore or .hgignore files
|
98
|
+
ignore_files = [".hgignore", ".gitignore"]
|
99
|
+
ignore_files.each do |ignore_file|
|
100
|
+
abs_ignore_file = env[:root_path].to_s + "/" + ignore_file
|
101
|
+
if File.exist?(abs_ignore_file)
|
102
|
+
command = command + ["--exclude-from", abs_ignore_file]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
r = Vagrant::Util::Subprocess.execute(*command)
|
107
|
+
if r.exit_code != 0
|
108
|
+
raise Errors::RsyncError,
|
109
|
+
:guestpath => guestpath,
|
110
|
+
:hostpath => hostpath,
|
111
|
+
:stderr => r.stderr
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def ssh_key_options(ssh_info)
|
119
|
+
# Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
|
120
|
+
Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
require "fog"
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module Openstack
|
6
|
+
class Config < Vagrant.plugin("2", :config)
|
7
|
+
# The API key to access Openstack.
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
attr_accessor :api_key
|
11
|
+
|
12
|
+
# The region to access Openstack. If nil, it will default
|
13
|
+
# to DFW.
|
14
|
+
# (formerly know as 'endpoint')
|
15
|
+
#
|
16
|
+
# expected to be a symbol - :dfw (default), :ord, :lon
|
17
|
+
#
|
18
|
+
# Users should preference the openstack_region setting over openstack_compute_url
|
19
|
+
attr_accessor :openstack_region
|
20
|
+
|
21
|
+
# The compute_url to access Openstack. If nil, it will default
|
22
|
+
# to DFW.
|
23
|
+
# (formerly know as 'endpoint')
|
24
|
+
#
|
25
|
+
# expected to be a string url -
|
26
|
+
# 'https://dfw.servers.api.openstackcloud.com/v2'
|
27
|
+
# 'https://ord.servers.api.openstackcloud.com/v2'
|
28
|
+
# 'https://lon.servers.api.openstackcloud.com/v2'
|
29
|
+
#
|
30
|
+
# alternatively, can use constants if you require 'fog/openstack' in your Vagrantfile
|
31
|
+
# Fog::Compute::OpenstackV2::DFW_ENDPOINT
|
32
|
+
# Fog::Compute::OpenstackV2::ORD_ENDPOINT
|
33
|
+
# Fog::Compute::OpenstackV2::LON_ENDPOINT
|
34
|
+
#
|
35
|
+
# Users should preference the openstack_region setting over openstack_compute_url
|
36
|
+
attr_accessor :openstack_compute_url
|
37
|
+
|
38
|
+
# The authenication endpoint. This defaults to Openstack's global authentication endpoint.
|
39
|
+
# Users of the London data center should specify the following:
|
40
|
+
# https://lon.identity.api.openstackcloud.com/v2.0
|
41
|
+
attr_writer :openstack_auth_url
|
42
|
+
|
43
|
+
# Network configurations for the instance
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
attr_accessor :network
|
47
|
+
|
48
|
+
# The flavor of server to launch, either the ID or name. This
|
49
|
+
# can also be a regular expression to partially match a name.
|
50
|
+
attr_accessor :flavor
|
51
|
+
|
52
|
+
# The name or ID of the image to use. This can also be a regular
|
53
|
+
# expression to partially match a name.
|
54
|
+
attr_accessor :image
|
55
|
+
|
56
|
+
# Alternately, if a keypair were already uploaded to Openstack,
|
57
|
+
# the key name could be provided.
|
58
|
+
#
|
59
|
+
# @return [String]
|
60
|
+
attr_accessor :key_name
|
61
|
+
|
62
|
+
# A Hash of metadata that will be sent to the instance for configuration
|
63
|
+
#
|
64
|
+
# @return [Hash]
|
65
|
+
attr_accessor :metadata
|
66
|
+
|
67
|
+
# The option that indicates RackConnect usage or not.
|
68
|
+
#
|
69
|
+
# @return [Boolean]
|
70
|
+
attr_accessor :rackconnect
|
71
|
+
|
72
|
+
#
|
73
|
+
# The name of the openstack project on witch the vm will be created.
|
74
|
+
#
|
75
|
+
attr_accessor :tenant_name
|
76
|
+
|
77
|
+
# The name of the server. This defaults to the name of the machine
|
78
|
+
# defined by Vagrant (via `config.vm.define`), but can be overriden
|
79
|
+
# here.
|
80
|
+
attr_accessor :server_name
|
81
|
+
|
82
|
+
# Specify the availability zone in which to create the instance
|
83
|
+
attr_accessor :availability_zone
|
84
|
+
|
85
|
+
# The username to access Openstack.
|
86
|
+
#
|
87
|
+
# @return [String]
|
88
|
+
attr_accessor :username
|
89
|
+
|
90
|
+
# The name of the keypair to use.
|
91
|
+
#
|
92
|
+
# @return [String]
|
93
|
+
attr_accessor :keypair_name
|
94
|
+
|
95
|
+
# The SSH username to use with this OpenStack instance. This overrides
|
96
|
+
# the `config.ssh.username` variable.
|
97
|
+
#
|
98
|
+
# @return [String]
|
99
|
+
attr_accessor :ssh_username
|
100
|
+
|
101
|
+
# The SSH timeout use after server creation. If server startup is too long
|
102
|
+
# the timeout value can be increase with this variable. Default is 60 seconds
|
103
|
+
#
|
104
|
+
# @return [Integer]
|
105
|
+
attr_accessor :ssh_timeout
|
106
|
+
|
107
|
+
# The disk configuration value.
|
108
|
+
# * AUTO - The server is built with a single partition the size of the target flavor disk. The file system is automatically adjusted to fit the entire partition.
|
109
|
+
# This keeps things simple and automated. AUTO is valid only for images and servers with a single partition that use the EXT3 file system.
|
110
|
+
# This is the default setting for applicable Openstack base images.
|
111
|
+
#
|
112
|
+
# * MANUAL - The server is built using whatever partition scheme and file system is in the source image. If the target flavor disk is larger,
|
113
|
+
# the remaining disk space is left unpartitioned. This enables images to have non-EXT3 file systems, multiple partitions,
|
114
|
+
# and so on, and enables you to manage the disk configuration.
|
115
|
+
#
|
116
|
+
# This defaults to MANUAL
|
117
|
+
attr_accessor :disk_config
|
118
|
+
|
119
|
+
# Opt files/directories in to the rsync operation performed by this provider
|
120
|
+
#
|
121
|
+
# @return [Array]
|
122
|
+
attr_accessor :rsync_includes
|
123
|
+
|
124
|
+
# The floating IP address from the IP pool which will be assigned to the instance.
|
125
|
+
#
|
126
|
+
# @return [String]
|
127
|
+
attr_accessor :floating_ip
|
128
|
+
|
129
|
+
# Sync folder method. Can be either "rsync" or "none"
|
130
|
+
#
|
131
|
+
# @return [String]
|
132
|
+
attr_accessor :sync_method
|
133
|
+
|
134
|
+
def initialize
|
135
|
+
@api_key = UNSET_VALUE
|
136
|
+
@openstack_region = UNSET_VALUE
|
137
|
+
@openstack_compute_url = UNSET_VALUE
|
138
|
+
@openstack_auth_url = UNSET_VALUE
|
139
|
+
@flavor = UNSET_VALUE
|
140
|
+
@image = UNSET_VALUE
|
141
|
+
@rackconnect = UNSET_VALUE
|
142
|
+
@availability_zone = UNSET_VALUE
|
143
|
+
@tenant_name = UNSET_VALUE
|
144
|
+
@server_name = UNSET_VALUE
|
145
|
+
@username = UNSET_VALUE
|
146
|
+
@disk_config = UNSET_VALUE
|
147
|
+
@network = UNSET_VALUE
|
148
|
+
@rsync_includes = []
|
149
|
+
@keypair_name = UNSET_VALUE
|
150
|
+
@ssh_username = UNSET_VALUE
|
151
|
+
@ssh_timeout = UNSET_VALUE
|
152
|
+
@floating_ip = UNSET_VALUE
|
153
|
+
@sync_method = UNSET_VALUE
|
154
|
+
end
|
155
|
+
|
156
|
+
def finalize!
|
157
|
+
@api_key = nil if @api_key == UNSET_VALUE
|
158
|
+
@openstack_region = nil if @openstack_region == UNSET_VALUE
|
159
|
+
@openstack_compute_url = nil if @openstack_compute_url == UNSET_VALUE
|
160
|
+
@openstack_auth_url = nil if @openstack_auth_url == UNSET_VALUE
|
161
|
+
@flavor = /m1.tiny/ if @flavor == UNSET_VALUE # TODO No default value
|
162
|
+
@image = /cirros/ if @image == UNSET_VALUE # TODO No default value
|
163
|
+
@rackconnect = nil if @rackconnect == UNSET_VALUE
|
164
|
+
@availability_zone = nil if @availability_zone == UNSET_VALUE
|
165
|
+
@tenant_name = nil if @tenant_name == UNSET_VALUE
|
166
|
+
@server_name = nil if @server_name == UNSET_VALUE
|
167
|
+
@metadata = nil if @metadata == UNSET_VALUE
|
168
|
+
@network = nil if @network == UNSET_VALUE
|
169
|
+
@username = nil if @username == UNSET_VALUE
|
170
|
+
@disk_config = nil if @disk_config == UNSET_VALUE
|
171
|
+
@rsync_includes = nil if @rsync_includes.empty?
|
172
|
+
@floating_ip = nil if @floating_ip == UNSET_VALUE
|
173
|
+
@sync_method = "rsync" if @sync_method == UNSET_VALUE
|
174
|
+
|
175
|
+
# Keypair defaults to nil
|
176
|
+
@keypair_name = nil if @keypair_name == UNSET_VALUE
|
177
|
+
|
178
|
+
# The SSH values by default are nil, and the top-level config
|
179
|
+
# `config.ssh` values are used.
|
180
|
+
@ssh_username = nil if @ssh_username == UNSET_VALUE
|
181
|
+
@ssh_timeout = 60 if @ssh_timeout == UNSET_VALUE
|
182
|
+
end
|
183
|
+
|
184
|
+
# @note Currently, you must authenticate against the UK authenication endpoint to access the London Data center.
|
185
|
+
# Hopefully this method makes the experience more seemless for users of the UK cloud.
|
186
|
+
def openstack_auth_url
|
187
|
+
if (@openstack_auth_url.nil? || @openstack_auth_url == UNSET_VALUE) && lon_region?
|
188
|
+
Fog::Openstack::UK_AUTH_ENDPOINT
|
189
|
+
else
|
190
|
+
@openstack_auth_url
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def rsync_include(inc)
|
195
|
+
@rsync_includes << inc
|
196
|
+
end
|
197
|
+
|
198
|
+
def validate(machine)
|
199
|
+
errors = _detected_errors
|
200
|
+
|
201
|
+
errors << I18n.t("vagrant_openstack.config.api_key required") if !@api_key
|
202
|
+
errors << I18n.t("vagrant_openstack.config.username required") if !@username
|
203
|
+
errors << I18n.t("vagrant_openstack.config.keypair_name required") if !@keypair_name
|
204
|
+
|
205
|
+
{
|
206
|
+
:openstack_compute_url => @openstack_compute_url,
|
207
|
+
:openstack_auth_url => @openstack_auth_url
|
208
|
+
}.each_pair do |key, value|
|
209
|
+
errors << I18n.t("vagrant_openstack.config.invalid_uri", :key => key, :uri => value) unless value.nil? || valid_uri?(value)
|
210
|
+
end
|
211
|
+
|
212
|
+
{ "Openstack Provider" => errors }
|
213
|
+
end
|
214
|
+
|
215
|
+
private
|
216
|
+
|
217
|
+
def lon_region?
|
218
|
+
openstack_region && openstack_region != UNSET_VALUE && openstack_region.to_sym == :lon
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def valid_uri? value
|
224
|
+
uri = URI.parse value
|
225
|
+
uri.kind_of?(URI::HTTP)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Openstack
|
5
|
+
module Errors
|
6
|
+
class VagrantOpenstackError < Vagrant::Errors::VagrantError
|
7
|
+
error_namespace("vagrant_openstack.errors")
|
8
|
+
end
|
9
|
+
|
10
|
+
class CreateBadState < VagrantOpenstackError
|
11
|
+
error_key(:create_bad_state)
|
12
|
+
end
|
13
|
+
|
14
|
+
class NoMatchingFlavor < VagrantOpenstackError
|
15
|
+
error_key(:no_matching_flavor)
|
16
|
+
end
|
17
|
+
|
18
|
+
class NoMatchingImage < VagrantOpenstackError
|
19
|
+
error_key(:no_matching_image)
|
20
|
+
end
|
21
|
+
|
22
|
+
class SyncMethodError < VagrantOpenstackError
|
23
|
+
error_key(:sync_method_error)
|
24
|
+
end
|
25
|
+
|
26
|
+
class RsyncError < VagrantOpenstackError
|
27
|
+
error_key(:rsync_error)
|
28
|
+
end
|
29
|
+
|
30
|
+
class SshUnavailable < VagrantOpenstackError
|
31
|
+
error_key(:ssh_unavailble)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "log4r"
|
2
|
+
require "restclient"
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module Openstack
|
7
|
+
class OpenstackClient
|
8
|
+
|
9
|
+
def initialize()
|
10
|
+
@logger = Log4r::Logger.new("vagrant_openstack::openstack_client")
|
11
|
+
@token = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def authenticate(env)
|
15
|
+
@logger.debug("Authenticating on Keystone")
|
16
|
+
config = env[:machine].provider_config
|
17
|
+
authentication = RestClient.post(config.openstack_auth_url, {
|
18
|
+
:auth => {
|
19
|
+
:tenantName => config.tenant_name,
|
20
|
+
:passwordCredentials => {
|
21
|
+
:username => config.username,
|
22
|
+
:password => config.api_key
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}.to_json,
|
26
|
+
:content_type => :json,
|
27
|
+
:accept => :json)
|
28
|
+
|
29
|
+
@token = JSON.parse(authentication)['access']['token']['id']
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_all_flavors(env)
|
33
|
+
config = env[:machine].provider_config
|
34
|
+
flavors_json = RestClient.get(config.openstack_compute_url + "/flavors",
|
35
|
+
{"X-Auth-Token" => @token, :accept => :json})
|
36
|
+
return JSON.parse(flavors_json)['flavors'].map { |fl| Item.new(fl['id'], fl['name']) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_all_images(env)
|
40
|
+
config = env[:machine].provider_config
|
41
|
+
images_json = RestClient.get(config.openstack_compute_url + "/images",
|
42
|
+
{"X-Auth-Token" => @token, :accept => :json})
|
43
|
+
return JSON.parse(images_json)['images'].map { |im| Item.new(im['id'], im['name']) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def create_server(env, name, image_ref, flavor_ref, keypair)
|
47
|
+
config = env[:machine].provider_config
|
48
|
+
server = RestClient.post(config.openstack_compute_url + "/servers", {
|
49
|
+
:server => {
|
50
|
+
:name => name,
|
51
|
+
:imageRef => image_ref,
|
52
|
+
:flavorRef => flavor_ref,
|
53
|
+
:key_name => keypair
|
54
|
+
}
|
55
|
+
}.to_json,
|
56
|
+
"X-Auth-Token" => @token,
|
57
|
+
:accept => :json,
|
58
|
+
:content_type => :json)
|
59
|
+
return JSON.parse(server)['server']['id']
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_server_details(env, server_id)
|
63
|
+
config = env[:machine].provider_config
|
64
|
+
server_details = RestClient.get(config.openstack_compute_url + "/servers/" + server_id,
|
65
|
+
"X-Auth-Token" => @token,
|
66
|
+
:accept => :json)
|
67
|
+
return JSON.parse(server_details)['server']
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_floating_ip(env, server_id, floating_ip)
|
71
|
+
config = env[:machine].provider_config
|
72
|
+
server_details = RestClient.post(config.openstack_compute_url + "/servers/" + server_id + "/action", {
|
73
|
+
:addFloatingIp => {
|
74
|
+
:address => floating_ip
|
75
|
+
}
|
76
|
+
}.to_json,
|
77
|
+
"X-Auth-Token" => @token,
|
78
|
+
:accept => :json,
|
79
|
+
:content_type => :json)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class Item
|
84
|
+
attr_accessor :id, :name
|
85
|
+
def initialize(id, name)
|
86
|
+
@id = id
|
87
|
+
@name = name
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|