vagrant_filoo 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +61 -0
- data/Gemfile +14 -0
- data/LICENSE +22 -0
- data/README.md +207 -0
- data/Rakefile +5 -0
- data/doc/img_res/filoo_logo.png +0 -0
- data/doc/img_res/filoo_wolke.png +0 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/filoo.box +0 -0
- data/lib/vagrant_filoo/action/create_server.rb +51 -0
- data/lib/vagrant_filoo/action/get_images.rb +21 -0
- data/lib/vagrant_filoo/action/is_created.rb +22 -0
- data/lib/vagrant_filoo/action/is_stopped.rb +18 -0
- data/lib/vagrant_filoo/action/message_already_created.rb +16 -0
- data/lib/vagrant_filoo/action/message_not_created.rb +16 -0
- data/lib/vagrant_filoo/action/read_ssh_info.rb +40 -0
- data/lib/vagrant_filoo/action/read_state.rb +65 -0
- data/lib/vagrant_filoo/action/start_instance.rb +48 -0
- data/lib/vagrant_filoo/action/stop_instance.rb +31 -0
- data/lib/vagrant_filoo/action/terminate_instance.rb +24 -0
- data/lib/vagrant_filoo/action/test.rb +2 -0
- data/lib/vagrant_filoo/action.rb +184 -0
- data/lib/vagrant_filoo/cloud_compute.rb +629 -0
- data/lib/vagrant_filoo/config.rb +54 -0
- data/lib/vagrant_filoo/errors.rb +81 -0
- data/lib/vagrant_filoo/plugin.rb +73 -0
- data/lib/vagrant_filoo/provider.rb +52 -0
- data/lib/vagrant_filoo/util/timer.rb +17 -0
- data/lib/vagrant_filoo/version.rb +5 -0
- data/lib/vagrant_filoo.rb +17 -0
- data/locales/en.yml +122 -0
- data/sample_config/Vagrantfile_example +23 -0
- data/spec/spec_helper.rb +0 -0
- data/spec/vagrant_filoo/config_spec.rb +70 -0
- data/templates/metadata.json.erb +3 -0
- data/templates/vagrant-filoo_package_Vagrantfile.erb +5 -0
- data/vagrant_filoo.gemspec +58 -0
- metadata +178 -0
@@ -0,0 +1,629 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require_relative 'errors'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module Filoo
|
7
|
+
module CloudCompute
|
8
|
+
LOGGER = Log4r::Logger.new('vagrant_filoo::cloud_compute')
|
9
|
+
|
10
|
+
################################
|
11
|
+
# Application specific methods #
|
12
|
+
################################
|
13
|
+
CREATE_SERVER_RESOURCE = '/vserver/create'
|
14
|
+
DELETE_SERVER_RESOURCE = '/vserver/delete'
|
15
|
+
LIST_SERVER_RESOURCE ='/vserver/list'
|
16
|
+
SERVERSTATUS_RESOURCE = '/vserver/status'
|
17
|
+
START_RESOURCE = '/vserver/start'
|
18
|
+
STOP_RESOURCE = '/vserver/stop'
|
19
|
+
LIST_NIC_RESOURCE = '/vserver/list_nic'
|
20
|
+
ADD_NIC_RESOURCE = '/vserver/add_nic'
|
21
|
+
DELETE_NIC_RESOURCE = '/vserver/del_nic'
|
22
|
+
|
23
|
+
########################################
|
24
|
+
# Virtual Server Creation and checking #
|
25
|
+
########################################
|
26
|
+
|
27
|
+
CREATE_SERVER_TIMEOUT = 30
|
28
|
+
VALID_TYPES = ['dynamic','fixed']
|
29
|
+
VALID_CPU_COUNTS = [1, 2, 3, 4, 5, 6, 7, 8]
|
30
|
+
VALID_RAM = [128, 256, 512, 1024, 2048, 3072, 4096, 5120, 6144, 7186, 8192]
|
31
|
+
|
32
|
+
#####################################################################
|
33
|
+
# create a virtual server with the given parameters
|
34
|
+
# parameters {hash} with following fields
|
35
|
+
# -type=(dynamic|fixed) : dynmaic (minutely) or vServer (monthly)
|
36
|
+
# -cpu=(1-8): Anzahl vCPUs
|
37
|
+
# -ram=(128,256,512,1024,2048,3072,4096,5120,6144,7186,8192): Ram in MB
|
38
|
+
# -hdd=(10-2000): HDDp Space in GB, 10GB-Steps (10,20,30,...)
|
39
|
+
# -cd_imageid ID. Only for images with autoinstall=1.
|
40
|
+
####################################################################
|
41
|
+
|
42
|
+
def self.createServer(params, baseUrl, apiKey)
|
43
|
+
checkServerParams(params)
|
44
|
+
createServerUrl = baseUrl + CREATE_SERVER_RESOURCE
|
45
|
+
jobId = call4JobId createServerUrl, apiKey, params
|
46
|
+
vmid = nil;
|
47
|
+
jobResult = nil
|
48
|
+
|
49
|
+
begin
|
50
|
+
jobResult = waitJobDone(jobId, baseUrl, apiKey, CREATE_SERVER_TIMEOUT)
|
51
|
+
vmid = jobResult[:result]['vmid']
|
52
|
+
|
53
|
+
if jobResult[:result]['vmid'].nil?
|
54
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
55
|
+
code: 500,
|
56
|
+
message: "Unexpected return value to Api Call POST " + createServerUrl + " #{params} " + {:jobid => jobId}.to_json,
|
57
|
+
description: "Response has no field vmid in result. Response: " + jobResult.to_json
|
58
|
+
end
|
59
|
+
|
60
|
+
rescue VagrantPlugins::Filoo::Errors::FilooJobResultTimeoutError => e
|
61
|
+
raise VagrantPlugins::Filoo::Errors::CreateInstanceTimeout,
|
62
|
+
job_id: jobId,
|
63
|
+
timeout: e.timeout
|
64
|
+
rescue VagrantPlugins::Filoo::Errors::FilooJobFailedError => e
|
65
|
+
vmid = jobResult[:result]['vmid']
|
66
|
+
end
|
67
|
+
|
68
|
+
serverStatus = nil;
|
69
|
+
checkParams = {:type => params[:type],
|
70
|
+
:cpu => params[:cpu],
|
71
|
+
:ram => params[:ram],
|
72
|
+
:hdd => params[:hdd]}
|
73
|
+
|
74
|
+
begin
|
75
|
+
serverStatus = self.checkServerStatus(vmid, checkParams, baseUrl, apiKey)
|
76
|
+
rescue VagrantPlugins::Filoo::Errors::FilooApiError => e
|
77
|
+
|
78
|
+
if e.code == 403
|
79
|
+
raise VagrantPlugins::Filoo::Errors::UnexpectedStateError,
|
80
|
+
resource: LIST_SERVER_RESOURCE,
|
81
|
+
jobid: jobResult[:jobid],
|
82
|
+
job_command: jobResult[:job_command],
|
83
|
+
state: serverList,
|
84
|
+
message: "Unexpected State of server list " + serverList.to_json,
|
85
|
+
description: "Server with vmid #{vmid} should have been created "
|
86
|
+
+ "(see #{baseUrl}#{LIST_SERVER_RESOURCE} action : list) "
|
87
|
+
+ "Server is not created though system gave feedback with status #{jobResult[:status]} "
|
88
|
+
+ "to task #{jobResult[:job_command]} #{jobResult[:job_param]} with jobid #{jobResult[:jobid]}"
|
89
|
+
end
|
90
|
+
|
91
|
+
raise e
|
92
|
+
end
|
93
|
+
|
94
|
+
serverStatus
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.checkServerParams params
|
98
|
+
|
99
|
+
if !params.is_a?(Hash)
|
100
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError,
|
101
|
+
message: "Invalid type of parameter params, must be Hash but is #{params.class}"
|
102
|
+
end
|
103
|
+
|
104
|
+
if params[:type].nil? or ! ['dynamic','fixed'].include? params[:type]
|
105
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError,
|
106
|
+
message: "Invalid value #{params[:type]} for configuration field type, must be one of the following numbers #{VALID_TYPES}"
|
107
|
+
end
|
108
|
+
|
109
|
+
if params[:cpu].nil? or ! VALID_CPU_COUNTS.include? params[:cpu]
|
110
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError,
|
111
|
+
message: "Invalid value #{params[:cpu]} for configuration field cpu, must be one of the following numbers #{VALID_CPU_COUNTS}"
|
112
|
+
end
|
113
|
+
|
114
|
+
if params[:ram].nil? or ! VALID_RAM.include? params[:ram]
|
115
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError,
|
116
|
+
message: "Invalid value #{params[:ram]} for configuration field ram, must be one of the following numbers #{VALID_RAM.to_json}"
|
117
|
+
end
|
118
|
+
|
119
|
+
if params[:hdd].nil? or params[:hdd] < 10 or params[:hdd] > 2000 or params[:hdd] % 10 != 0
|
120
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError,
|
121
|
+
message: "Invalid value #{params[:hd]} for configuration field hd, must be a number between 10-2000 "
|
122
|
+
+ " with steps of 10,20,30..."
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
# Server removal
|
128
|
+
DELETE_SERVER_TIMEOUT = 30
|
129
|
+
|
130
|
+
def self.deleteServer(vmid, baseUrl, apiKey)
|
131
|
+
deleteServereUrl = baseUrl + DELETE_SERVER_RESOURCE
|
132
|
+
jobId = call4JobId deleteServereUrl, apiKey, {:vmid => vmid}
|
133
|
+
jobResult = nil;
|
134
|
+
|
135
|
+
begin
|
136
|
+
jobResult = waitJobDone(jobId, baseUrl, apiKey, DELETE_SERVER_TIMEOUT)
|
137
|
+
rescue VagrantPlugins::Filoo::Errors::FilooJobResultTimeoutError => e
|
138
|
+
raise VagrantPlugins::Filoo::Errors::DeleteInstanceTimeout,
|
139
|
+
job_id: jobId,
|
140
|
+
timeout: e.timeout
|
141
|
+
end
|
142
|
+
|
143
|
+
serverList = self.getServers(baseUrl + LIST_SERVER_RESOURCE, apiKey)
|
144
|
+
|
145
|
+
if !serverList["#{vmid}"].nil?
|
146
|
+
raise VagrantPlugins::Filoo::Errors::UnexpectedStateError,
|
147
|
+
resource: LIST_SERVER_RESOURCE,
|
148
|
+
jobid: jobResult[:jobid],
|
149
|
+
job_command: jobResult[:job_command],
|
150
|
+
state: serverList,
|
151
|
+
message: "Unexpected State of server list " + serverList.to_json,
|
152
|
+
description: "Server with vmid #{vmid} should have been deleted from server list but is not "
|
153
|
+
+ "(see #{baseUrl}#{LIST_SERVER_RESOURCE} action : list) "
|
154
|
+
+ "though system gave feedback with status #{jobResult[:status]} to task "
|
155
|
+
+ "#{jobResult[:job_command]} #{jobResult[:job_param]} with jobid #{jobResult[:jobid]}"
|
156
|
+
end
|
157
|
+
|
158
|
+
return serverList
|
159
|
+
end
|
160
|
+
|
161
|
+
# start server
|
162
|
+
|
163
|
+
START_INSTANCE_TIMEOUT = 60
|
164
|
+
|
165
|
+
def self.startInstance(vmid, baseUrl, apiKey, filooConfig)
|
166
|
+
|
167
|
+
shouldNotChangeParams = {
|
168
|
+
:type => filooConfig.type,
|
169
|
+
:cpu => filooConfig.cpu,
|
170
|
+
:ram => filooConfig.ram,
|
171
|
+
:hdd => filooConfig.hdd
|
172
|
+
}
|
173
|
+
|
174
|
+
begin
|
175
|
+
compareServerStatus(vmid, shouldNotChangeParams, baseUrl, apiKey)
|
176
|
+
rescue VagrantPlugins::Filoo::Errors::InvaildServerParameterError => e
|
177
|
+
paramKey = "#{e.paramName}"
|
178
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError,
|
179
|
+
message: "Can not update filoo provider parameter '#{e.paramName}'. Parameter 'filoo.#{e.paramName}' must be set to #{e.serverStatus[paramKey]}.
|
180
|
+
Please create new instance if you need updated this parameters."
|
181
|
+
end
|
182
|
+
|
183
|
+
nicList = self.listNic(vmid, baseUrl, apiKey)
|
184
|
+
|
185
|
+
if filooConfig.additional_nic && nicList.count < 1
|
186
|
+
self.addNic(vmid, baseUrl, apiKey)
|
187
|
+
elsif !filooConfig.additional_nic && nicList.count > 0
|
188
|
+
self.deleteNic(vmid, baseUrl, apiKey)
|
189
|
+
end
|
190
|
+
|
191
|
+
url = "#{baseUrl}#{START_RESOURCE}"
|
192
|
+
jobId = call4JobId url, apiKey, {:vmid => vmid}
|
193
|
+
jobResult = nil;
|
194
|
+
|
195
|
+
begin
|
196
|
+
jobResult = waitJobDone(jobId, baseUrl, apiKey, START_INSTANCE_TIMEOUT)
|
197
|
+
rescue VagrantPlugins::Filoo::Errors::FilooJobResultTimeoutError => e
|
198
|
+
raise VagrantPlugins::Filoo::Errors::StartInstanceTimeout,
|
199
|
+
job_id: jobId,
|
200
|
+
timeout: e.timeout
|
201
|
+
end
|
202
|
+
|
203
|
+
serverStatus = nil;
|
204
|
+
|
205
|
+
begin
|
206
|
+
serverStatus = checkServerStatus(vmid, {:vmid => vmid, :vmstatus => "running"}, baseUrl, apiKey)
|
207
|
+
|
208
|
+
rescue VagrantPlugins::Filoo::Errors::FilooApiError => e
|
209
|
+
if e.code == 403
|
210
|
+
raise VagrantPlugins::Filoo::Errors::UnexpectedStateError,
|
211
|
+
resource: LIST_SERVER_RESOURCE,
|
212
|
+
jobid: jobResult[:jobid],
|
213
|
+
job_command: jobResult[:job_command],
|
214
|
+
state: serverList,
|
215
|
+
message: "Unexpected State of server list " + serverList.to_json,
|
216
|
+
description: "Server with vmid #{vmid} should be in list "
|
217
|
+
+ "(see #{baseUrl}#{LIST_SERVER_RESOURCE} action : list) "
|
218
|
+
+ "Server is not in list though system gave feedback with status #{jobResult[:status]} "
|
219
|
+
+ "to task #{jobResult[:job_command]} #{jobResult[:job_param]} with jobid #{jobResult[:jobid]}"
|
220
|
+
end
|
221
|
+
raise e
|
222
|
+
end
|
223
|
+
|
224
|
+
return serverStatus
|
225
|
+
end
|
226
|
+
|
227
|
+
# stop instance
|
228
|
+
|
229
|
+
STOP_INSTANCE_TIMEOUT = 60
|
230
|
+
|
231
|
+
def self.stopInstance(vmid, baseUrl, apiKey)
|
232
|
+
stopInstanceUrl = baseUrl + STOP_RESOURCE
|
233
|
+
jobId = call4JobId(stopInstanceUrl, apiKey, {:vmid => vmid})
|
234
|
+
jobResult = nil
|
235
|
+
|
236
|
+
begin
|
237
|
+
jobResult = waitJobDone(jobId, baseUrl, apiKey, STOP_INSTANCE_TIMEOUT)
|
238
|
+
rescue VagrantPlugins::Filoo::Errors::FilooJobResultTimeoutError => e
|
239
|
+
raise VagrantPlugins::Filoo::Errors::StopInstanceTimeout,
|
240
|
+
job_id: jobId,
|
241
|
+
timeout: e.timeout
|
242
|
+
end
|
243
|
+
|
244
|
+
serverStatus = nil;
|
245
|
+
|
246
|
+
begin
|
247
|
+
serverStatus = checkServerStatus(vmid, {:vmid => vmid, :vmstatus => "stopped"}, baseUrl, apiKey)
|
248
|
+
rescue VagrantPlugins::Filoo::Errors::FilooApiError => e
|
249
|
+
if e.code == 403
|
250
|
+
raise VagrantPlugins::Filoo::Errors::UnexpectedStateError,
|
251
|
+
resource: LIST_SERVER_RESOURCE,
|
252
|
+
jobid: jobResult[:jobid],
|
253
|
+
job_command: jobResult[:job_command],
|
254
|
+
state: serverList,
|
255
|
+
message: "Unexpected State of server list " + serverList.to_json,
|
256
|
+
description: "Server with vmid #{vmid} should be in list "
|
257
|
+
+ "(see #{baseUrl}#{LIST_SERVER_RESOURCE} action : list) "
|
258
|
+
+ "Server is not in list though system gave feedback with status #{jobResult[:status]} "
|
259
|
+
+ "to task #{jobResult[:job_command]} #{jobResult[:job_param]} with jobid #{jobResult[:jobid]}"
|
260
|
+
end
|
261
|
+
raise e
|
262
|
+
end
|
263
|
+
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
# list servers
|
268
|
+
|
269
|
+
def self.getServers(baseUrl, apiKey)
|
270
|
+
begin
|
271
|
+
serverList = self.call(baseUrl + LIST_SERVER_RESOURCE,apiKey, {:detailed => false})['return']
|
272
|
+
hashFromServerList(serverList)
|
273
|
+
rescue ArgumentError => e
|
274
|
+
raise ConfigError, e.message
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def self.hashFromServerList serverList
|
279
|
+
serversHash = {}
|
280
|
+
serverList.each { |serverInfo|
|
281
|
+
serversHash[serverInfo['vmid']] = serverInfo
|
282
|
+
serversHash[serverInfo['vmid']].delete('vmid')
|
283
|
+
}
|
284
|
+
return serversHash
|
285
|
+
end
|
286
|
+
|
287
|
+
def self.hashFromServerList serverList
|
288
|
+
serversHash = {}
|
289
|
+
serverList.each { |serverInfo|
|
290
|
+
serversHash[serverInfo['vmid']] = serverInfo
|
291
|
+
serversHash[serverInfo['vmid']].delete('vmid')
|
292
|
+
}
|
293
|
+
return serversHash
|
294
|
+
end
|
295
|
+
|
296
|
+
# list nic
|
297
|
+
|
298
|
+
def self.listNic(vmid, baseUrl, apiKey)
|
299
|
+
begin
|
300
|
+
return self.call(baseUrl + LIST_NIC_RESOURCE, apiKey, {:vmid => vmid})['return']
|
301
|
+
rescue ArgumentError => e
|
302
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError, message: e.message
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
# add nic
|
307
|
+
|
308
|
+
def self.addNic(vmid, baseUrl, apiKey)
|
309
|
+
|
310
|
+
begin
|
311
|
+
return self.call(baseUrl + ADD_NIC_RESOURCE, apiKey, {:vmid => vmid})['return']
|
312
|
+
rescue ArgumentError => e
|
313
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError, message: e.message
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
# add nic
|
319
|
+
|
320
|
+
def self.deleteNic(vmid, baseUrl, apiKey)
|
321
|
+
|
322
|
+
begin
|
323
|
+
return self.call(baseUrl + DELETE_NIC_RESOURCE, apiKey, {:vmid => vmid})['return']
|
324
|
+
rescue ArgumentError => e
|
325
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError, message: e.message
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
329
|
+
|
330
|
+
# server status
|
331
|
+
|
332
|
+
def self.getServerStatus(vmid, baseUrl, apiKey)
|
333
|
+
|
334
|
+
if vmid.nil?
|
335
|
+
return :not_created
|
336
|
+
end
|
337
|
+
|
338
|
+
begin
|
339
|
+
return self.call(baseUrl + SERVERSTATUS_RESOURCE, apiKey, {:vmid => vmid, :detailed => true})['return']
|
340
|
+
rescue ArgumentError => e
|
341
|
+
raise VagrantPlugins::Filoo::Errors::ConfigError, message: e.message
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
|
346
|
+
def self.checkServerStatus(vmid, shouldParams, baseUrl, apiKey)
|
347
|
+
|
348
|
+
begin
|
349
|
+
return compareServerStatus(vmid, shouldParams, baseUrl, apiKey)
|
350
|
+
rescue VagrantPlugins::Filoo::Errors::InvaildServerParameterError => e
|
351
|
+
raise VagrantPlugins::Filoo::Errors::UnexpectedStateError,
|
352
|
+
resource: SERVERSTATUS_RESOURCE,
|
353
|
+
state: e.serverStatus,
|
354
|
+
message: "Unexpected State of server " + serverStatus.to_json,
|
355
|
+
description: "Server with vmid #{vmid} should have following params set " + shouldParams.to_json
|
356
|
+
+ " but has status " + e.serverStatus
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
#
|
362
|
+
# Retrieves the Server status and compares it with the given shouldPramams
|
363
|
+
#
|
364
|
+
def self.compareServerStatus(vmid, shouldParams, baseUrl, apiKey)
|
365
|
+
serverStatus = self.getServerStatus(vmid, baseUrl, apiKey)
|
366
|
+
|
367
|
+
if serverStatus == :not_created
|
368
|
+
raise VagrantPlugins::Filoo::Errors::UnexpectedStateError,
|
369
|
+
state: serverStatus,
|
370
|
+
message: "Unexpected State of server " + serverStatus.to_json
|
371
|
+
end
|
372
|
+
|
373
|
+
serverStatus = JSON.parse(serverStatus.to_json)
|
374
|
+
shouldParams = JSON.parse(shouldParams.to_json)
|
375
|
+
shouldParams.each do |key, value|
|
376
|
+
|
377
|
+
if "#{value}" != "#{serverStatus[key]}"
|
378
|
+
raise VagrantPlugins::Filoo::Errors::InvaildServerParameterError.new(key, serverStatus[key], serverStatus),
|
379
|
+
resource: SERVERSTATUS_RESOURCE,
|
380
|
+
invalidKey: key,
|
381
|
+
invalidValue: value,
|
382
|
+
state: serverStatus,
|
383
|
+
message: "Unexpected State of server " + serverStatus.to_json,
|
384
|
+
description: "Server with vmid #{vmid} should have following params set " + shouldParams.to_json
|
385
|
+
+ " but has status " + serverStatus
|
386
|
+
end
|
387
|
+
|
388
|
+
end
|
389
|
+
return serverStatus
|
390
|
+
end
|
391
|
+
|
392
|
+
#images
|
393
|
+
IMAGES_RESOURCE = "/vserver/image"
|
394
|
+
|
395
|
+
def self.getAutoInstallImages(baseUrl, apiKey)
|
396
|
+
imageList = nil;
|
397
|
+
begin
|
398
|
+
imageList = self.call(baseUrl + IMAGES_RESOURCE, apiKey, {:action => "list"})['return']
|
399
|
+
rescue ArgumentError => e
|
400
|
+
raise ConfigError, e.message
|
401
|
+
end
|
402
|
+
autoInstallImagesHash = {}
|
403
|
+
imageList.each { |imageInfo|
|
404
|
+
if !imageInfo['cd'].nil? and imageInfo['autoinstall'] == 1
|
405
|
+
autoInstallImagesHash[imageInfo['cd']] = imageInfo['cd_imageid']
|
406
|
+
end
|
407
|
+
}
|
408
|
+
return autoInstallImagesHash;
|
409
|
+
end
|
410
|
+
|
411
|
+
#Image handling
|
412
|
+
|
413
|
+
def self.hashAutoInstallListFromImageList serverList
|
414
|
+
autoInstallImagesHash = {}
|
415
|
+
serverList.each { |imageInfo|
|
416
|
+
if !imageInfo['cd'].nil? and imageInfo['autoinstall'] == 1
|
417
|
+
autoInstallImagesHash[imageInfo['cd']] = imageInfo
|
418
|
+
autoInstallImagesHash[imageInfo['cd']].delete("cd")
|
419
|
+
end
|
420
|
+
}
|
421
|
+
return autoInstallImagesHash;
|
422
|
+
end
|
423
|
+
|
424
|
+
|
425
|
+
##########################################
|
426
|
+
# basic api call handling to https://api.filoo.de/api/v1/
|
427
|
+
############################################
|
428
|
+
|
429
|
+
SHOWJOB_RESOURCE = "/jobqueue/show/"
|
430
|
+
DEFAULT_TIMEOUT = 60
|
431
|
+
|
432
|
+
# asynchron calls
|
433
|
+
def self.call4JobId(url, apiKey, params)
|
434
|
+
apiCallPayload = nil
|
435
|
+
begin
|
436
|
+
apiCallPayload = self.call(url, apiKey, params)['return']
|
437
|
+
rescue ArgumentError => e
|
438
|
+
raise ConfigError, e.message
|
439
|
+
end
|
440
|
+
if !apiCallPayload.is_a?(Hash)
|
441
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
442
|
+
code: 500,
|
443
|
+
message: 'Unexpected return value to Api Call POST ' + url + ' ' + params.to_json,
|
444
|
+
description: 'Return value ' + apiCallPayload.to_json + ' is no a hash'
|
445
|
+
end
|
446
|
+
if apiCallPayload['jobid'].nil?
|
447
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
448
|
+
code: 500,
|
449
|
+
message: 'Unexpected return value to Api Call POST ' + url + ' ' + params.to_json,
|
450
|
+
description: 'Return value ' + apiCallPayload.to_json + ' has no field "jobid"'
|
451
|
+
end
|
452
|
+
apiCallPayload['jobid']
|
453
|
+
end
|
454
|
+
|
455
|
+
|
456
|
+
def self.waitJobDone(jobId, baseUrl, apiKey, timeout)
|
457
|
+
timeout = timeout.nil? ? DEFAULT_TIMEOUT : timeout
|
458
|
+
startTimeStamp = Time.now.to_f
|
459
|
+
result = nil;
|
460
|
+
while (result = requestJobStatusWithResult(jobId, baseUrl, apiKey)).nil?
|
461
|
+
if startTimeStamp - Time.now.to_f > timeout
|
462
|
+
raise Errors::FilooJobResultTimeoutError,
|
463
|
+
job_id: jobId,
|
464
|
+
timeout: timeout
|
465
|
+
end
|
466
|
+
sleep 3
|
467
|
+
end
|
468
|
+
result
|
469
|
+
end
|
470
|
+
|
471
|
+
def self.requestJobStatusWithResult(jobId, baseUrl, apiKey)
|
472
|
+
url = baseUrl + SHOWJOB_RESOURCE
|
473
|
+
params = {:jobid => jobId}
|
474
|
+
resp = nil
|
475
|
+
begin
|
476
|
+
resp = self.call(url, apiKey, {:jobid => jobId})
|
477
|
+
rescue ArgumentError => e
|
478
|
+
raise ConfigError, e.message
|
479
|
+
end
|
480
|
+
if resp['status']['description'] == "jobID not found"
|
481
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
482
|
+
code: 500,
|
483
|
+
message: "Unexpected return value to Api Call POST " + url + " " + {:jobid => jobId}.to_json,
|
484
|
+
code: 500,
|
485
|
+
description: "Requested jobid #{jobId} not found",
|
486
|
+
jobid: jobid
|
487
|
+
end
|
488
|
+
returnVal = resp['return']
|
489
|
+
if !returnVal.is_a?(Hash)
|
490
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
491
|
+
code: 500,
|
492
|
+
message: "Unexpected return value to Api Call POST " + url + " " + {:jobid => jobId}.to_json,
|
493
|
+
description: "Return value " + returnVal.to_json + " is not a Hash"
|
494
|
+
end
|
495
|
+
if returnVal['job_status'].nil?
|
496
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
497
|
+
code: 500,
|
498
|
+
message: "Unexpected return value to Api Call POST " + url + " " + {:jobid => jobId}.to_json,
|
499
|
+
description: 'JSON response ' + returnVal.to_json + ' has no Field "job_status"'
|
500
|
+
end
|
501
|
+
if returnVal['jobid'] != jobId
|
502
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
503
|
+
code: 500,
|
504
|
+
message: "Unexpected return value to Api Call POST " + url + " " + {:jobid => jobId}.to_json,
|
505
|
+
description: "Response references wrong jobid #{returnVal['jobid']} must refernce #{jobId}. Response: " + resp.to_json
|
506
|
+
end
|
507
|
+
if returnVal['job_param'].nil?
|
508
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
509
|
+
code: 500,
|
510
|
+
message: "Unexpected return value to Api Call POST " + url + " #{params} " + {:jobid => jobId}.to_json,
|
511
|
+
description: "Response has no field job_param in result. Response: " + returnVal.to_json
|
512
|
+
end
|
513
|
+
LOGGER.info("Filoo Job #{resp['return']['job_command']} #{resp['return']['job_status_text']}")
|
514
|
+
case returnVal['job_status_text']
|
515
|
+
when 'finished'
|
516
|
+
jobResult = nil
|
517
|
+
if !returnVal['job_result'].nil? and returnVal['job_result'] != ""
|
518
|
+
jobResult = JSON.parse(returnVal['job_result'])
|
519
|
+
end
|
520
|
+
return {:result => jobResult, :status => 'finished', jobid: jobId, job_command: returnVal['job_command'], job_param: returnVal['job_param']}
|
521
|
+
when 'failed', 'aborted'
|
522
|
+
raise VagrantPlugins::Filoo::Errors::FilooJobFailedError,
|
523
|
+
jobid: returnVal['jobid'],
|
524
|
+
job_command: returnVal['job_command'],
|
525
|
+
job_param: returnVal['job_param'],
|
526
|
+
message: "Job Execution Failed for Task #{returnVal['job_command']} with parameters #{returnVal['job_param']} and Job Id #{returnVal['jobid']}:" + resp.to_json
|
527
|
+
when 'new', 'processing'
|
528
|
+
return nil
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
# synchron call
|
533
|
+
def self.call(url, apiKey, params)
|
534
|
+
resp = doHttpCall(url, params, apiKey)
|
535
|
+
jsonResp = nil
|
536
|
+
begin
|
537
|
+
jsonResp = JSON.parse(resp.body)
|
538
|
+
rescue JSON::ParserError => e
|
539
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
540
|
+
code: 500,
|
541
|
+
message: "Can not parse JSON from response to POST " + url + " " + params.to_json,
|
542
|
+
description: "Can not parse " + resp.body + ": " + e.message
|
543
|
+
end
|
544
|
+
if !jsonResp['return'].nil?
|
545
|
+
return jsonResp
|
546
|
+
else
|
547
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
548
|
+
code: 500,
|
549
|
+
message: "No return field in response to POST " + url + " " + params.to_json,
|
550
|
+
description: "Response from api " + resp.body
|
551
|
+
end
|
552
|
+
return jsonResp
|
553
|
+
end
|
554
|
+
|
555
|
+
#http handling
|
556
|
+
def self.doHttpCall(url, params, apiKey)
|
557
|
+
if apiKey.nil? or apiKey == ""
|
558
|
+
raise ArgumentError, "filoo.filoo_api_key must be set"
|
559
|
+
end
|
560
|
+
if !(url =~ URI::regexp)
|
561
|
+
raise ArgumentError, "url must be a valid http resource but is #{url}"
|
562
|
+
end
|
563
|
+
|
564
|
+
boundary = createBoundary
|
565
|
+
headers = { Authorization: apiKey, :content_type => "multipart/form-data; boundary=----#{boundary}"}
|
566
|
+
body = createBody(params, boundary)
|
567
|
+
resp = nil
|
568
|
+
begin
|
569
|
+
resp = RestClient.post url, body, headers
|
570
|
+
rescue RestClient::BadRequest => e
|
571
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
572
|
+
code: e.http_code,
|
573
|
+
message: "Wrong parameter set #{params.to_json} on call to #{url}",
|
574
|
+
description: e.http_body
|
575
|
+
|
576
|
+
rescue RestClient::Unauthorized => e
|
577
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
578
|
+
code: e.http_code,
|
579
|
+
message: "Can not Authenticate with Api Key",
|
580
|
+
description: e.http_body
|
581
|
+
|
582
|
+
rescue RestClient::Forbidden => e
|
583
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
584
|
+
code: e.http_code,
|
585
|
+
message: "No Access granted on call to #{url} using parameters #{params.to_json}",
|
586
|
+
description: e.http_body
|
587
|
+
|
588
|
+
rescue RestClient::NotAcceptable => e
|
589
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
590
|
+
code: e.http_code,
|
591
|
+
message: "Async task triggered by call to #{url} using parameters #{params.to_json} is yet in queue",
|
592
|
+
description: e.http_body
|
593
|
+
|
594
|
+
rescue RestClient::RequestFailed => e
|
595
|
+
raise VagrantPlugins::Filoo::Errors::VagrantFilooError,
|
596
|
+
message: e.message
|
597
|
+
code -1
|
598
|
+
end
|
599
|
+
|
600
|
+
if resp.code != 200
|
601
|
+
raise VagrantPlugins::Filoo::Errors::FilooApiError,
|
602
|
+
code: jsonResp['status']['code'],
|
603
|
+
message: jsonResp['status']['message'],
|
604
|
+
description: jsonResp['status']['description']
|
605
|
+
end
|
606
|
+
|
607
|
+
return resp
|
608
|
+
end
|
609
|
+
|
610
|
+
def self.createBody(params, boundary)
|
611
|
+
body = ""
|
612
|
+
params.each do |name, value|
|
613
|
+
body = body + createPartFromParam(name, value, "------" + boundary)
|
614
|
+
end
|
615
|
+
body + "------" + boundary +"--"
|
616
|
+
end
|
617
|
+
|
618
|
+
def self.createPartFromParam(name, value, boundary)
|
619
|
+
"#{boundary}\nContent-Disposition: form-data; name=\"#{name}\"\n\n#{value}\n"
|
620
|
+
end
|
621
|
+
|
622
|
+
def self.createBoundary
|
623
|
+
random = ""; 16.times{random << ((rand(2)==1?65:97) + rand(25)).chr}
|
624
|
+
"VagrantFilooHttpClient#{random}"
|
625
|
+
end
|
626
|
+
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Filoo
|
5
|
+
class Config < Vagrant.plugin("2", :config)
|
6
|
+
# The access key ID for accessing Filoo.
|
7
|
+
#
|
8
|
+
# @return [String]
|
9
|
+
attr_accessor :filoo_api_key
|
10
|
+
attr_accessor :filoo_api_entry_point
|
11
|
+
attr_accessor :filoo_api_entry_point
|
12
|
+
|
13
|
+
attr_accessor :cd_image_name
|
14
|
+
attr_accessor :type
|
15
|
+
attr_accessor :cpu
|
16
|
+
attr_accessor :ram
|
17
|
+
attr_accessor :hdd
|
18
|
+
attr_accessor :additional_nic
|
19
|
+
|
20
|
+
def initialize()
|
21
|
+
@filoo_api_key = nil
|
22
|
+
@filoo_api_entry_point = nil
|
23
|
+
@cd_image_name = nil
|
24
|
+
@type = nil
|
25
|
+
@cpu = nil
|
26
|
+
@ram = nil
|
27
|
+
@hdd = nil
|
28
|
+
@additional_nic = nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# set security_groups
|
32
|
+
def security_groups=(value)
|
33
|
+
# convert value to array if necessary
|
34
|
+
@security_groups = value.is_a?(Array) ? value : [value]
|
35
|
+
end
|
36
|
+
|
37
|
+
def finalize!
|
38
|
+
# Try to get access keys from standard FILOO environment variables; they
|
39
|
+
# will default to nil if the environment variables are not present.
|
40
|
+
@filoo_api_key = ENV['FILOO_API_KEY'] if @filoo_api_key == nil
|
41
|
+
@filoo_api_entry_point = ENV['FILOO_API_ENTRY_POINT'] if @filoo_api_entry_point == nil
|
42
|
+
|
43
|
+
#set default values for machine
|
44
|
+
@cd_image_name = 'Debian 7.7 - 64bit' if @cd_image_name == nil
|
45
|
+
@type = 'dynamic' if @type == nil
|
46
|
+
@cpu = 1 if @cpu == nil
|
47
|
+
@ram = 128 if @ram == nil
|
48
|
+
@hdd = 10 if @hdd == nil
|
49
|
+
@additional_nic = false if @additional_nic == nil
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|