forj 1.0.1 → 1.0.2
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 +4 -4
- data/.gitignore +7 -0
- data/.gitreview +4 -0
- data/Gemfile +21 -19
- data/Gemfile.lock +71 -0
- data/bin/forj +126 -83
- data/forj.gemspec +64 -0
- data/{lib → forj}/defaults.yaml +23 -1
- data/lib/appinit.rb +5 -5
- data/lib/build_tmpl/build-env.py +293 -0
- data/lib/cloud_test.rb +121 -0
- data/lib/forj-settings.rb +52 -39
- data/lib/forj/ForjCli.rb +11 -10
- data/lib/forj/ForjCore.rb +8 -6
- data/lib/forj/process/ForjProcess.rb +345 -82
- data/lib/ssh.rb +81 -20
- metadata +110 -80
- data/lib/compute.rb +0 -36
- data/lib/connection.rb +0 -144
- data/lib/down.rb +0 -60
- data/lib/forj-account.rb +0 -294
- data/lib/forj-config.rb +0 -522
- data/lib/helpers.rb +0 -56
- data/lib/lib-forj/lib/core/core.rb +0 -1740
- data/lib/lib-forj/lib/core/definition.rb +0 -441
- data/lib/lib-forj/lib/core/definition_internal.rb +0 -306
- data/lib/lib-forj/lib/core_process/CloudProcess.rb +0 -334
- data/lib/lib-forj/lib/core_process/global_process.rb +0 -406
- data/lib/lib-forj/lib/core_process/network_process.rb +0 -603
- data/lib/lib-forj/lib/lib-forj.rb +0 -37
- data/lib/lib-forj/lib/providers/hpcloud/Hpcloud.rb +0 -419
- data/lib/lib-forj/lib/providers/hpcloud/compute.rb +0 -108
- data/lib/lib-forj/lib/providers/hpcloud/network.rb +0 -117
- data/lib/lib-forj/lib/providers/hpcloud/security_groups.rb +0 -67
- data/lib/lib-forj/lib/providers/templates/compute.rb +0 -42
- data/lib/lib-forj/lib/providers/templates/core.rb +0 -61
- data/lib/lib-forj/lib/providers/templates/network.rb +0 -33
- data/lib/log.rb +0 -162
- data/lib/network.rb +0 -365
- data/lib/repositories.rb +0 -222
- data/lib/security.rb +0 -207
- data/lib/ssh.sh +0 -185
- data/spec/connection_spec.rb +0 -52
- data/spec/forj-config_spec.rb +0 -237
- data/spec/repositories_spec.rb +0 -50
@@ -1,334 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# encoding: UTF-8
|
3
|
-
|
4
|
-
# (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
|
18
|
-
# It requires Core objects to be defined + default ForjProcess functions.
|
19
|
-
|
20
|
-
require File.join($CORE_PROCESS_PATH, "global_process.rb")
|
21
|
-
require File.join($CORE_PROCESS_PATH, "network_process.rb")
|
22
|
-
|
23
|
-
# Define framework object on BaseDefinition
|
24
|
-
class BaseDefinition
|
25
|
-
|
26
|
-
# All objects used by this process are built from a Controller
|
27
|
-
process_default :use_controller => true
|
28
|
-
|
29
|
-
# predefined list of objects.
|
30
|
-
# Links between objects is not predefined. To do it, use needs declaration in your provider class.
|
31
|
-
|
32
|
-
# object to get list of services
|
33
|
-
# Defines Process handler to call
|
34
|
-
define_obj(:services,
|
35
|
-
{
|
36
|
-
:create_e => :connect
|
37
|
-
})
|
38
|
-
obj_needs :data, :auth_uri
|
39
|
-
obj_needs :data, :account_id
|
40
|
-
obj_needs :data, :account_key
|
41
|
-
obj_needs :data, :tenant
|
42
|
-
|
43
|
-
undefine_attribute :id # Do not return any predefined ID
|
44
|
-
undefine_attribute :name # Do not return any predefined NAME
|
45
|
-
|
46
|
-
|
47
|
-
# compute_connection
|
48
|
-
define_obj(:compute_connection,
|
49
|
-
{
|
50
|
-
:create_e => :connect # Will call ForjProcess connect
|
51
|
-
})
|
52
|
-
obj_needs :data, :account_id
|
53
|
-
obj_needs :data, :account_key
|
54
|
-
obj_needs :data, :auth_uri
|
55
|
-
obj_needs :data, :tenant
|
56
|
-
obj_needs :data, :compute
|
57
|
-
|
58
|
-
undefine_attribute :id # Do not return any predefined ID
|
59
|
-
undefine_attribute :name # Do not return any predefined NAME
|
60
|
-
|
61
|
-
# network_connection
|
62
|
-
define_obj(:network_connection,
|
63
|
-
{
|
64
|
-
:create_e => :connect
|
65
|
-
})
|
66
|
-
obj_needs :data, :account_id
|
67
|
-
obj_needs :data, :account_key
|
68
|
-
obj_needs :data, :auth_uri
|
69
|
-
obj_needs :data, :tenant
|
70
|
-
obj_needs :data, :network
|
71
|
-
|
72
|
-
undefine_attribute :id # Do not return any predefined ID
|
73
|
-
undefine_attribute :name # Do not return any predefined NAME
|
74
|
-
|
75
|
-
# ************************************ Network Object
|
76
|
-
# Identify the network
|
77
|
-
|
78
|
-
define_obj(:network,
|
79
|
-
:create_e => :forj_get_or_create_network,
|
80
|
-
:query_e => :forj_query_network,
|
81
|
-
:get_e => :forj_get_network,
|
82
|
-
:delete_e => :forj_delete_network
|
83
|
-
)
|
84
|
-
obj_needs :CloudObject, :network_connection
|
85
|
-
obj_needs :data, :network_name, { :for => [:create_e] }
|
86
|
-
|
87
|
-
obj_needs_optional
|
88
|
-
obj_needs :data, :subnetwork_name, { :for => [:create_e] }
|
89
|
-
|
90
|
-
def_query_attribute :external # true if network is external or not.
|
91
|
-
|
92
|
-
# ************************************ SubNetwork Object
|
93
|
-
# Identify subnetwork as part of network.
|
94
|
-
define_obj(:subnetwork,
|
95
|
-
:create_e => :forj_get_or_create_subnetwork
|
96
|
-
)
|
97
|
-
|
98
|
-
obj_needs :CloudObject, :network_connection
|
99
|
-
obj_needs :CloudObject, :network
|
100
|
-
obj_needs :data, :subnetwork_name
|
101
|
-
|
102
|
-
def_query_attribute :network_id
|
103
|
-
|
104
|
-
# ************************************ Port Object
|
105
|
-
# Identify port attached to network
|
106
|
-
define_obj :port, :nohandler => true
|
107
|
-
|
108
|
-
obj_needs :CloudObject, :network_connection
|
109
|
-
def_attribute :device_id
|
110
|
-
|
111
|
-
def_query_attribute :network_id
|
112
|
-
def_query_attribute :device_owner
|
113
|
-
|
114
|
-
|
115
|
-
# ************************************ Router Object
|
116
|
-
# Identify the router of a network.
|
117
|
-
define_obj(:router,
|
118
|
-
{
|
119
|
-
:create_e => :forj_get_or_create_router,
|
120
|
-
# :query_e => :forj_query_router,
|
121
|
-
# :get_e => :forj_get_router,
|
122
|
-
:update_e => :forj_update_router
|
123
|
-
# :delete_e => :forj_delete_router
|
124
|
-
})
|
125
|
-
obj_needs :CloudObject, :network_connection
|
126
|
-
obj_needs :CloudObject, :network, { :for => [:create_e] }
|
127
|
-
obj_needs :CloudObject, :subnetwork, { :for => [:create_e] }
|
128
|
-
obj_needs_optional
|
129
|
-
obj_needs :data, :router_name, { :for => [:create_e] }
|
130
|
-
|
131
|
-
def_attribute :gateway_network_id
|
132
|
-
|
133
|
-
# ************************************ Router interface Object
|
134
|
-
# Identify interface attached to a router
|
135
|
-
# This object will probably be moved to controller task
|
136
|
-
# To keep the network model more generic.
|
137
|
-
|
138
|
-
# No process handler defined. Just Controller object
|
139
|
-
define_obj :router_interface, :nohandler => true
|
140
|
-
|
141
|
-
obj_needs :CloudObject, :network_connection
|
142
|
-
obj_needs :CloudObject, :router, { :for => [:create_e] }
|
143
|
-
obj_needs :CloudObject, :subnetwork, { :for => [:create_e] }
|
144
|
-
|
145
|
-
undefine_attribute :name
|
146
|
-
undefine_attribute :id
|
147
|
-
|
148
|
-
# Identify an external network thanks to the network router.
|
149
|
-
define_obj(:external_network,
|
150
|
-
{
|
151
|
-
:create_e => :forj_get_or_create_ext_net,
|
152
|
-
:query_e => :forj_query_external_network
|
153
|
-
})
|
154
|
-
|
155
|
-
obj_needs :CloudObject, :network_connection
|
156
|
-
obj_needs :CloudObject, :router
|
157
|
-
|
158
|
-
|
159
|
-
# ************************************ Security groups Object
|
160
|
-
# Identify security_groups
|
161
|
-
define_obj(:security_groups,
|
162
|
-
{
|
163
|
-
:create_e => :forj_get_or_create_sg,
|
164
|
-
:query_e => :forj_query_sg,
|
165
|
-
:delete_e => :forj_delete_sg
|
166
|
-
})
|
167
|
-
|
168
|
-
obj_needs :CloudObject, :network_connection
|
169
|
-
obj_needs :data, :security_group, { :for => [:create_e] }
|
170
|
-
obj_needs_optional
|
171
|
-
obj_needs :data, :sg_desc, { :for => [:create_e] }
|
172
|
-
|
173
|
-
# ************************************ Security group rules Object
|
174
|
-
# Identify Rules attached to the security group
|
175
|
-
define_obj(:rule,
|
176
|
-
{
|
177
|
-
:create_e => :forj_get_or_create_rule,
|
178
|
-
:query_e => :forj_query_rule
|
179
|
-
# :delete_e => :forj_delete_rule
|
180
|
-
})
|
181
|
-
|
182
|
-
undefine_attribute :name # Do not return any predefined name attribute
|
183
|
-
|
184
|
-
obj_needs :CloudObject, :network_connection
|
185
|
-
obj_needs :CloudObject, :security_groups, { :for => [:create_e] }
|
186
|
-
obj_needs :data, :sg_id, { :for => [:create_e], :extract_from => [:security_groups, :attrs, :id] }
|
187
|
-
obj_needs :data, :dir, { :for => [:create_e] }
|
188
|
-
predefine_data_value :IN, { :desc => "Input NAT/firewall rule map type" }
|
189
|
-
predefine_data_value :OUT, { :desc => "Output NAT/firewall rule map type" }
|
190
|
-
obj_needs :data, :proto, { :for => [:create_e] }
|
191
|
-
obj_needs :data, :port_min, { :for => [:create_e] }
|
192
|
-
obj_needs :data, :port_max, { :for => [:create_e] }
|
193
|
-
obj_needs :data, :addr_map, { :for => [:create_e] }
|
194
|
-
|
195
|
-
# ************************************ keypairs Object
|
196
|
-
# Identify keypairs
|
197
|
-
define_obj(:keypairs,
|
198
|
-
{
|
199
|
-
:create_e => :forj_get_or_create_keypair,
|
200
|
-
:query_e => :forj_query_keypair
|
201
|
-
# :delete_e => :forj_delete_keypair
|
202
|
-
})
|
203
|
-
|
204
|
-
obj_needs :CloudObject, :compute_connection
|
205
|
-
obj_needs :data, :keypair_name, { :for => [:create_e] }
|
206
|
-
obj_needs :data, :keypair_path, { :for => [:create_e] }
|
207
|
-
|
208
|
-
obj_needs_optional
|
209
|
-
obj_needs :data, :public_key, { :for => [:create_e] }
|
210
|
-
|
211
|
-
def_attribute :public_key
|
212
|
-
|
213
|
-
# ************************************ Image Object
|
214
|
-
# Identify image
|
215
|
-
define_obj(:image,
|
216
|
-
{
|
217
|
-
:create_e => :forj_get_or_create_image,
|
218
|
-
:query_e => :forj_query_image
|
219
|
-
# :get_e => :forj_get_image
|
220
|
-
# :update_e => :forj_update_image
|
221
|
-
# :delete_e => :forj_delete_image
|
222
|
-
})
|
223
|
-
|
224
|
-
obj_needs :CloudObject, :compute_connection
|
225
|
-
obj_needs :data, :image_name, { :for => [:create_e] }
|
226
|
-
|
227
|
-
# ************************************ Flavor Object
|
228
|
-
# Identify flavor
|
229
|
-
define_obj(:flavor,
|
230
|
-
{
|
231
|
-
:create_e => :forj_get_or_create_flavor,
|
232
|
-
:query_e => :forj_query_flavor
|
233
|
-
# :get_e => :forj_get_flavor,
|
234
|
-
# :update_e => :forj_update_flavor,
|
235
|
-
# :delete_e => :forj_delete_flavor
|
236
|
-
})
|
237
|
-
|
238
|
-
obj_needs :CloudObject, :compute_connection
|
239
|
-
obj_needs :data, :flavor_name, { :for => [:create_e] }
|
240
|
-
# Cloud provider will need to map to one of those predefined flavors.
|
241
|
-
# limitation values may match exactly or at least ensure those limitation
|
242
|
-
# are under provider limitation
|
243
|
-
# ie, at least the CloudProcess limitation can less than the Cloud provider defines.
|
244
|
-
# CloudProcess EHD = 160, then Provider EHD = 200 is ok
|
245
|
-
# but Provider EHD = 150 is not ok.
|
246
|
-
predefine_data_value('tiny', { :desc => "VCU: 1, RAM:512M, HD:1G, EHD: 0G, Swap: 0G" })
|
247
|
-
predefine_data_value('xsmall', { :desc => "VCU: 1, RAM:1G, HD:10G, EHD: 10G, Swap: 0G" })
|
248
|
-
predefine_data_value('small', { :desc => "VCU: 2, RAM:2G, HD:30G, EHD: 10G, Swap: 0G" })
|
249
|
-
predefine_data_value('medium', { :desc => "VCU: 2, RAM:4G, HD:30G, EHD: 50G, Swap: 0G" })
|
250
|
-
predefine_data_value('large', { :desc => "VCU: 4, RAM:8G, HD:30G, EHD: 100G, Swap: 0G" })
|
251
|
-
predefine_data_value('xlarge', { :desc => "VCU: 8, RAM:16G, HD:30G, EHD: 200G, Swap: 0G" })
|
252
|
-
|
253
|
-
# ************************************ Internet network Object
|
254
|
-
# Define Internet network
|
255
|
-
#
|
256
|
-
# This object contains the logic to ensure the router's network has a gateway to the external network (internet)
|
257
|
-
# is capable to connect to internet
|
258
|
-
# And to create this connection if possible.
|
259
|
-
|
260
|
-
define_obj(:internet_network, :nohandler => true )
|
261
|
-
|
262
|
-
obj_needs :CloudObject, :external_network # External network to connect if needed.
|
263
|
-
|
264
|
-
# ************************************ SERVER Object
|
265
|
-
# Identify the server to use/build on the network/...
|
266
|
-
define_obj(:server,
|
267
|
-
{
|
268
|
-
:create_e => :forj_get_or_create_server,
|
269
|
-
:query_e => :forj_query_server,
|
270
|
-
:get_e => :forj_get_server
|
271
|
-
# :update_e => :forj_update_server,
|
272
|
-
# :delete_e => :forj_delete_server
|
273
|
-
})
|
274
|
-
|
275
|
-
obj_needs :CloudObject, :compute_connection
|
276
|
-
obj_needs :CloudObject, :flavor, { :for => [:create_e] }
|
277
|
-
obj_needs :CloudObject, :network, { :for => [:create_e] }
|
278
|
-
obj_needs :CloudObject, :security_groups, { :for => [:create_e] }
|
279
|
-
obj_needs :CloudObject, :keypairs, { :for => [:create_e] }
|
280
|
-
obj_needs :CloudObject, :image, { :for => [:create_e] }
|
281
|
-
obj_needs :data, :server_name, { :for => [:create_e] }
|
282
|
-
|
283
|
-
obj_needs_optional
|
284
|
-
obj_needs :data, :user_data, { :for => [:create_e] }
|
285
|
-
obj_needs :data, :meta_data, { :for => [:create_e] }
|
286
|
-
|
287
|
-
def_attribute :status
|
288
|
-
predefine_data_value :create, { :desc => "Server is creating." }
|
289
|
-
predefine_data_value :boot, { :desc => "Server is booting." }
|
290
|
-
predefine_data_value :active, { :desc => "Server is started." }
|
291
|
-
def_attribute :private_ip_address
|
292
|
-
def_attribute :public_ip_address
|
293
|
-
|
294
|
-
# ************************************ SERVER Addresses Object
|
295
|
-
# Object representing the list of IP addresses attached to a server.
|
296
|
-
define_obj(:public_ip,
|
297
|
-
:create_e => :forj_get_or_assign_public_address,
|
298
|
-
:query_e => :forj_query_public_address
|
299
|
-
# :get_e => :forj_get_address
|
300
|
-
# :update_e => :forj_update_address
|
301
|
-
# :delete_e => :forj_delete_address
|
302
|
-
)
|
303
|
-
|
304
|
-
obj_needs :CloudObject, :compute_connection
|
305
|
-
obj_needs :CloudObject, :server
|
306
|
-
|
307
|
-
def_attribute :server_id
|
308
|
-
def_attribute :public_ip
|
309
|
-
undefine_attribute :name # No name to extract
|
310
|
-
|
311
|
-
# ************************************ SERVER Console Object
|
312
|
-
# Object representing the console log attached to a server
|
313
|
-
|
314
|
-
define_obj(:server_log,
|
315
|
-
{
|
316
|
-
:get_e => :forj_get_server_log
|
317
|
-
})
|
318
|
-
|
319
|
-
obj_needs :CloudObject, :server
|
320
|
-
obj_needs :data, :log_lines
|
321
|
-
undefine_attribute :name
|
322
|
-
undefine_attribute :id
|
323
|
-
def_attribute :output
|
324
|
-
|
325
|
-
# ************************************ Internet SERVER Object
|
326
|
-
# internet server is a server connected to the internet network.
|
327
|
-
define_obj(:internet_server, :nohandler => true )
|
328
|
-
|
329
|
-
obj_needs :CloudObject, :internet_network
|
330
|
-
obj_needs :CloudObject, :server
|
331
|
-
obj_needs :CloudObject, :public_ip
|
332
|
-
|
333
|
-
|
334
|
-
end
|
@@ -1,406 +0,0 @@
|
|
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
|