lorj 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.gitreview +4 -0
  4. data/Gemfile +25 -0
  5. data/Gemfile.lock +34 -0
  6. data/LICENSE.txt +14 -0
  7. data/README.md +652 -0
  8. data/Rakefile +24 -0
  9. data/bin/cloud_test.rb +81 -0
  10. data/example/students_1/process/Students.rb +20 -0
  11. data/example/students_1/students.rb +16 -0
  12. data/example/students_2/process/Students.rb +27 -0
  13. data/example/students_2/students.rb +36 -0
  14. data/example/students_3/controller/yaml_students.rb +94 -0
  15. data/example/students_3/controller/yaml_students_controller.rb +123 -0
  16. data/example/students_3/process/students.rb +118 -0
  17. data/example/students_3/students.rb +93 -0
  18. data/example/students_4/controller/yaml_students.rb +82 -0
  19. data/example/students_4/controller/yaml_students_controller.rb +141 -0
  20. data/example/students_4/process/students.rb +112 -0
  21. data/example/students_4/students.rb +103 -0
  22. data/example/yaml_students/students.rb +78 -0
  23. data/example/yaml_students/yaml_students.rb +115 -0
  24. data/lib/concept.md +111 -0
  25. data/lib/core/core.rb +723 -0
  26. data/lib/core/definition.rb +505 -0
  27. data/lib/core/definition_internal.rb +338 -0
  28. data/lib/core/lorj-basecontroller.rb +90 -0
  29. data/lib/core/lorj-basedefinition.rb +1079 -0
  30. data/lib/core/lorj-baseprocess.rb +231 -0
  31. data/lib/core/lorj-data.rb +567 -0
  32. data/lib/core/lorj-keypath.rb +115 -0
  33. data/lib/core_process/CloudProcess.rb +334 -0
  34. data/lib/core_process/global_process.rb +406 -0
  35. data/lib/core_process/network_process.rb +603 -0
  36. data/lib/img/.directory +4 -0
  37. data/lib/img/account_data_access.png +0 -0
  38. data/lib/img/config_data_access.png +0 -0
  39. data/lib/img/forj-lib-concept.png +0 -0
  40. data/lib/lorj/version.rb +3 -0
  41. data/lib/lorj.rb +51 -0
  42. data/lib/prc-account.rb +339 -0
  43. data/lib/prc-config.rb +1023 -0
  44. data/lib/prc-logging.rb +183 -0
  45. data/lib/prc.rb +108 -0
  46. data/lib/providers/hpcloud/Hpcloud.rb +419 -0
  47. data/lib/providers/hpcloud/compute.rb +108 -0
  48. data/lib/providers/hpcloud/network.rb +117 -0
  49. data/lib/providers/hpcloud/security_groups.rb +67 -0
  50. data/lib/providers/mock/Mock.rb +141 -0
  51. data/lib/providers/openstack/Openstack.rb +47 -0
  52. data/lib/providers/templates/compute.rb +42 -0
  53. data/lib/providers/templates/core.rb +61 -0
  54. data/lib/providers/templates/network.rb +33 -0
  55. data/lorj-spec/defaults.yaml +26 -0
  56. data/lorj.gemspec +39 -0
  57. data/spec/forj-account_spec.rb +75 -0
  58. data/spec/forj-config_spec.rb +196 -0
  59. metadata +164 -0
@@ -0,0 +1,406 @@
1
+ # encoding: UTF-8
2
+
3
+ # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ class SSLErrorMgt
18
+
19
+ def initialize(iMaxRetry = 5)
20
+ @iRetry = 0
21
+ @iMaxRetry = iMaxRetry
22
+ end
23
+
24
+ def ErrorDetected(message,backtrace, e)
25
+ if message.match('SSLv2/v3 read server hello A: unknown protocol')
26
+ if @iRetry <@iMaxRetry
27
+ sleep(2)
28
+ @iRetry+=1
29
+ print "%s/%s try... 'unknown protocol' SSL Error\r" % [@iRetry, @iMaxRetry] if $FORJ_LOGGER.level == 0
30
+ return false
31
+ else
32
+ Logging.error('Too many retry. %s' % message)
33
+ return true
34
+ end
35
+ elsif e.is_a?(Excon::Errors::InternalServerError)
36
+ if @iRetry <@iMaxRetry
37
+ sleep(2)
38
+ @iRetry+=1
39
+ print "%s/%s try... %s\n" % [@iRetry, @iMaxRetry, ANSI.red(e.class)] if $FORJ_LOGGER.level == 0
40
+ return false
41
+ else
42
+ Logging.error('Too many retry. %s' % message)
43
+ return true
44
+ end
45
+ else
46
+ Logging.error("Exception %s: %s\n%s" % [e.class, message,backtrace.join("\n")])
47
+ return true
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+
54
+ class CloudProcess < BaseProcess
55
+ def connect(sCloudObj, hParams)
56
+ oSSLError = SSLErrorMgt.new # Retry object
57
+ Logging.debug("%s:%s Connecting to '%s' - Project '%s'" % [self.class, sCloudObj, config.get(:provider), hParams[:tenant]])
58
+ begin
59
+ controler.connect(sCloudObj)
60
+ rescue => e
61
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
62
+ retry
63
+ end
64
+ Logging.error('%s:%s: Unable to connect.\n%s' % [self.class, sCloudObj, e.message ])
65
+ nil
66
+ end
67
+ end
68
+ end
69
+
70
+ # ---------------------------------------------------------------------------
71
+ # Keypair management
72
+ # ---------------------------------------------------------------------------
73
+ class CloudProcess
74
+ def forj_get_or_create_keypair(sCloudObj, hParams)
75
+ sKeypair_name = hParams[:keypair_name]
76
+ # setup has configured and copied the appropriate key to forj keypairs.
77
+
78
+ hKeys = keypair_detect(sKeypair_name, File.expand_path(hParams[:keypair_path]))
79
+ if hKeys[:private_key_exist? ]
80
+ hParams[:private_key_file] = File.join(hKeys[:keypair_path], hKeys[:private_key_name])
81
+ Logging.info("Openssh private key file '%s' exists." % hParams[:private_key_file])
82
+ end
83
+ if hKeys[:public_key_exist? ]
84
+ hParams[:public_key_file] = File.join(hKeys[:keypair_path], hKeys[:public_key_name])
85
+ else
86
+ Logging.fatal("Public key file is not found. Please run 'forj setup %s'" % config[:account_name])
87
+ end
88
+
89
+ Logging.state("Searching for keypair '%s'" % [sKeypair_name] )
90
+
91
+ keypairs = forj_query_keypair(sCloudObj, {:name => sKeypair_name}, hParams)
92
+ if keypairs.length > 0
93
+ keypair = keypairs[0]
94
+ # Check the public key with the one found here, locally.
95
+ if not keypair[:public_key].nil? and keypair[:public_key] != ""
96
+ begin
97
+ local_pub_key = File.read(hParams[:public_key_file])
98
+ rescue => e
99
+ Logging.error("Unable to read '%s'.\n%s",[hParams[:public_key_file], e.message] )
100
+ keypair[:coherent] = false
101
+ else
102
+ if local_pub_key.split(' ')[1].strip == keypair[:public_key].split(' ')[1].strip
103
+ Logging.info("keypair '%s' local files are coherent with keypair in your cloud service. You will be able to connect to your box over SSH." % sKeypair_name)
104
+ keypair[:coherent] = true
105
+ else
106
+ keypair[:coherent] = false
107
+ Logging.warning("Your local keypair file '%s' are incoherent with public key '%s' found in your cloud. You won't be able to access your box with this keypair.\nPublic key found in the cloud:\n%s" % [hParams[:public_key_file], sKeypair_name, keypair[:public_key]])
108
+ end
109
+ end
110
+ else
111
+ keypair[:coherent] = false
112
+ Logging.warning("Unable to verify keypair coherence between your cloud and your local SSH keys. The cloud controller did not provided ':public_key'")
113
+ end
114
+ else
115
+ config[:public_key] = File.read(hParams[:public_key_file])
116
+ keypair = create_keypair(sCloudObj, hParams)
117
+ if not hKeys[:private_key_exist? ]
118
+ keypair[:coherent] = false
119
+ else
120
+ keypair[:coherent] = true
121
+ end
122
+ end
123
+ # Adding information about key files.
124
+ keypair[:private_key_file] = hParams[:private_key_file]
125
+ keypair[:public_key_file] = hParams[:public_key_file]
126
+ keypair
127
+ end
128
+
129
+ def forj_query_keypair(sCloudObj, sQuery, hParams)
130
+ key_name = hParams[:keypair_name]
131
+ oSSLError = SSLErrorMgt.new
132
+ begin
133
+ oList = controler.query(sCloudObj, sQuery)
134
+ query_single(sCloudObj, oList, sQuery, key_name)
135
+ rescue => e
136
+ if not oSSLError.ErrorDetected(e.message, e.backtrace, e)
137
+ retry
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+ def create_keypair(sCloudObj, hParams)
144
+ key_name = hParams[:keypair_name]
145
+ Logging.state("Importing keypair '%s'" % [key_name])
146
+ oSSLError=SSLErrorMgt.new
147
+ begin
148
+ keypair = controler.create(sCloudObj)
149
+ Logging.info("Keypair '%s' imported." % [keypair[:name]])
150
+ rescue StandardError => e
151
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
152
+ retry
153
+ end
154
+ Logging.error "error importing keypair '%s'" % [key_name]
155
+ end
156
+ keypair
157
+ end
158
+
159
+ def keypair_detect(keypair_name, key_fullpath)
160
+ # Build key data information structure.
161
+ # Take care of priv with or without .pem and pubkey with pub.
162
+
163
+ key_basename = File.basename(key_fullpath)
164
+ key_path = File.expand_path(File.dirname(key_fullpath))
165
+
166
+ mObj = key_basename.match(/^(.*?)(\.pem|\.pub)?$/)
167
+ key_basename = mObj[1]
168
+
169
+ private_key_ext = nil
170
+ private_key_ext = "" if File.exists?(File.join(key_path, key_basename))
171
+ private_key_ext = '.pem' if File.exists?(File.join(key_path, key_basename + '.pem'))
172
+ if private_key_ext
173
+ private_key_exist = true
174
+ private_key_name = key_basename + private_key_ext
175
+ else
176
+ private_key_exist = false
177
+ private_key_name = key_basename
178
+ end
179
+
180
+ public_key_exist = File.exists?(File.join(key_path, key_basename + '.pub'))
181
+ public_key_name = key_basename + '.pub'
182
+
183
+
184
+ {:keypair_name => keypair_name,
185
+ :keypair_path => key_path, :key_basename => key_basename,
186
+ :private_key_name => private_key_name, :private_key_exist? => private_key_exist,
187
+ :public_key_name => public_key_name, :public_key_exist? => public_key_exist,
188
+ }
189
+ end
190
+
191
+ end
192
+
193
+ # ---------------------------------------------------------------------------
194
+ # flavor management
195
+ # ---------------------------------------------------------------------------
196
+ class CloudProcess
197
+ # Depending on clouds/rights, we can create flavor or not.
198
+ # Usually, flavor records already exists, and the controller may map them
199
+ # CloudProcess predefines some values. Consult CloudProcess.rb for details
200
+ def forj_get_or_create_flavor(sCloudObj, hParams)
201
+ sFlavor_name = hParams[:flavor_name]
202
+ Logging.state("Searching for flavor '%s'" % [sFlavor_name] )
203
+
204
+ flavors = query_flavor(sCloudObj, {:name => sFlavor_name}, hParams)
205
+ if flavors.length == 0
206
+ if not hParams[:create]
207
+ Logging.error("Unable to create %s '%s'. Creation is not supported." % [sCloudObj, sFlavor_name])
208
+ ForjLib::Data.new.set(nil, sCloudObj)
209
+ else
210
+ create_flavor(sCloudObj,hParams)
211
+ end
212
+ else
213
+ flavors[0]
214
+ end
215
+ end
216
+
217
+ # Should return 1 or 0 flavor.
218
+ def query_flavor(sCloudObj, sQuery, hParams)
219
+ sFlavor_name = hParams[:flavor_name]
220
+ oList = forj_query_flavor(sCloudObj, sQuery, hParams)
221
+ query_single(sCloudObj, oList, sQuery, sFlavor_name)
222
+ end
223
+
224
+ # Should return 1 or 0 flavor.
225
+ def forj_query_flavor(sCloudObj, sQuery, hParams)
226
+ sFlavor_name = hParams[:flavor_name]
227
+ oSSLError = SSLErrorMgt.new
228
+ begin
229
+ oList = controler.query(sCloudObj, sQuery)
230
+ rescue => e
231
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
232
+ retry
233
+ end
234
+ end
235
+ oList
236
+ end
237
+ end
238
+
239
+ # ---------------------------------------------------------------------------
240
+ # Image management
241
+ # ---------------------------------------------------------------------------
242
+ class CloudProcess < BaseProcess
243
+ def forj_get_or_create_image(sCloudObj, hParams)
244
+ sImage_name = hParams[:image_name]
245
+ Logging.state("Searching for image '%s'" % [sImage_name] )
246
+
247
+ search_the_image(sCloudObj, {:name => sImage_name}, hParams)
248
+ # No creation possible.
249
+ end
250
+
251
+ def search_the_image(sCloudObj, sQuery, hParams)
252
+ image_name = hParams[:image_name]
253
+ images = forj_query_image(sCloudObj, sQuery, hParams)
254
+ case images.length()
255
+ when 0
256
+ Logging.info("No image '%s' found" % [ image_name ] )
257
+ nil
258
+ else
259
+ Logging.info("Found image '%s'." % [ image_name ])
260
+ images[0]
261
+ end
262
+ end
263
+
264
+ def forj_query_image(sCloudObj, sQuery, hParams)
265
+ oSSLError = SSLErrorMgt.new
266
+ begin
267
+ controler.query(sCloudObj, sQuery)
268
+ rescue => e
269
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
270
+ retry
271
+ end
272
+ end
273
+ end
274
+ end
275
+
276
+ # ---------------------------------------------------------------------------
277
+ # Server management
278
+ # ---------------------------------------------------------------------------
279
+ class CloudProcess < BaseProcess
280
+ # Process Handler functions
281
+ def forj_get_or_create_server(sCloudObj, hParams)
282
+ sServer_name = hParams[:server_name]
283
+ Logging.state("Searching for server '%s'" % [sServer_name] )
284
+ servers = forj_query_server(sCloudObj, {:name => sServer_name}, hParams)
285
+ if servers.length > 0
286
+ # Get server details
287
+ forj_get_server(sCloudObj, servers[0][:attrs][:id], hParams)
288
+ else
289
+ create_server(sCloudObj, hParams)
290
+ end
291
+ end
292
+
293
+ def forj_query_server(sCloudObj, sQuery, hParams)
294
+ server_name = "Undefined"
295
+ server_name = sQuery[:name] if sQuery.key?(:name)
296
+ oSSLError = SSLErrorMgt.new
297
+ begin
298
+ oList = controler.query(sCloudObj, sQuery)
299
+ query_single(sCloudObj, oList, sQuery, server_name)
300
+ rescue => e
301
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
302
+ retry
303
+ end
304
+ end
305
+ end
306
+
307
+ def forj_get_server(sCloudObj, sId, hParams)
308
+ oSSLError = SSLErrorMgt.new
309
+ begin
310
+ controler.get(sCloudObj, sId)
311
+ rescue => e
312
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
313
+ retry
314
+ end
315
+ end
316
+ end
317
+
318
+ # Internal Process function
319
+ def create_server(sCloudObj, hParams)
320
+ name = hParams[:server_name]
321
+ begin
322
+ Logging.info("boot: meta-data provided.") if hParams[:meta_data]
323
+ Logging.info("boot: user-data provided.") if hParams[:user_data]
324
+ Logging.state('creating server %s' % [name])
325
+ server = controler.create(sCloudObj)
326
+ Logging.info("%s '%s' created." % [sCloudObj, name])
327
+ rescue => e
328
+ Logging.fatal(1, "Unable to create server '%s'" % name, e)
329
+ end
330
+ server
331
+ end
332
+
333
+ def forj_get_server_log(sCloudObj, sId, hParams)
334
+ oSSLError = SSLErrorMgt.new
335
+ begin
336
+ controler.get(sCloudObj, sId)
337
+ rescue => e
338
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
339
+ retry
340
+ end
341
+ end
342
+ end
343
+ end
344
+ # ---------------------------------------------------------------------------
345
+ # Addresses management
346
+ # ---------------------------------------------------------------------------
347
+ class CloudProcess < BaseProcess
348
+ # Process Handler functions
349
+ def forj_get_or_assign_public_address(sCloudObj, hParams)
350
+ # Function which to assign a public IP address to a server.
351
+ sServer_name = hParams[:server, :name]
352
+
353
+ Logging.state("Searching public IP for server '%s'" % [sServer_name] )
354
+ addresses = controler.query(sCloudObj, {:server_id => hParams[:server, :id]})
355
+ if addresses.length == 0
356
+ assign_address(sCloudObj, hParams)
357
+ else
358
+ addresses[0]
359
+ end
360
+ end
361
+
362
+ def forj_query_public_address(sCloudObj, sQuery, hParams)
363
+ server_name = hParams[:server, :name]
364
+ oSSLError = SSLErrorMgt.new
365
+ begin
366
+ sInfo = {
367
+ :notfound => "No %s for '%s' found",
368
+ :checkmatch => "Found 1 %s. checking exact match for server '%s'.",
369
+ :nomatch => "No %s for '%s' match",
370
+ :found => "Found %s '%s' for #{server_name}.",
371
+ :more => "Found several %s. Searching for '%s'.",
372
+ :items => :public_ip
373
+ }
374
+ oList = controler.query(sCloudObj, sQuery)
375
+ query_single(sCloudObj, oList, sQuery, server_name, sInfo)
376
+ rescue => e
377
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
378
+ retry
379
+ end
380
+ end
381
+ end
382
+
383
+ def forj_get_public_address(sCloudObj, sId, hParams)
384
+ oSSLError = SSLErrorMgt.new
385
+ begin
386
+ controler.get(sCloudObj, sId)
387
+ rescue => e
388
+ if not oSSLError.ErrorDetected(e.message,e.backtrace, e)
389
+ retry
390
+ end
391
+ end
392
+ end
393
+
394
+ # Internal Process function
395
+ def assign_address(sCloudObj, hParams)
396
+ name = hParams[:server, :name]
397
+ begin
398
+ Logging.state('Getting public IP for server %s' % [name])
399
+ ip_address = controler.create(sCloudObj)
400
+ Logging.info("Public IP '%s' for server '%s' assigned." % [ip_address[:public_ip], name])
401
+ rescue => e
402
+ Logging.fatal(1, "Unable to assign a public IP to server '%s'" % name, e)
403
+ end
404
+ ip_address
405
+ end
406
+ end