svengali 0.2.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/LICENSE +20 -0
  2. data/README +0 -0
  3. data/README.rdoc +17 -0
  4. data/Rakefile +47 -0
  5. data/VERSION +1 -0
  6. data/api_document020_en.pdf +0 -0
  7. data/api_document020_ja.pdf +0 -0
  8. data/api_document_en.pptx +0 -0
  9. data/api_document_ja.pptx +0 -0
  10. data/lib/svengali.rb +2 -0
  11. data/lib/svengali/config.rb +78 -0
  12. data/lib/svengali/ext_string.rb +55 -0
  13. data/lib/svengali/ext_string/command.yml +6 -0
  14. data/lib/svengali/ext_string/path.yml +6 -0
  15. data/lib/svengali/file_io.rb +106 -0
  16. data/lib/svengali/machine.rb +123 -0
  17. data/lib/svengali/platforms/debian.rb +5 -0
  18. data/lib/svengali/platforms/default.rb +4 -0
  19. data/lib/svengali/plugins/eucalyptus.rb +339 -0
  20. data/lib/svengali/plugins/machine_config.rb +126 -0
  21. data/lib/svengali/plugins/package.rb +7 -0
  22. data/lib/svengali/ssh.rb +106 -0
  23. data/lib/svengali/svengali.rb +19 -0
  24. data/lib/svengali/util.rb +117 -0
  25. data/rdoc/classes/CLibIPAddr.html +230 -0
  26. data/rdoc/classes/Cloud.html +506 -0
  27. data/rdoc/classes/Config.html +151 -0
  28. data/rdoc/classes/Config/ConfigFile.html +319 -0
  29. data/rdoc/classes/ExtStr.html +209 -0
  30. data/rdoc/classes/ExtStrAccessor.html +183 -0
  31. data/rdoc/classes/FileIO.html +415 -0
  32. data/rdoc/classes/Machine.html +771 -0
  33. data/rdoc/classes/MachineMaster.html +117 -0
  34. data/rdoc/classes/Platform.html +121 -0
  35. data/rdoc/classes/SSH.html +315 -0
  36. data/rdoc/created.rid +1 -0
  37. data/rdoc/files/README.html +101 -0
  38. data/rdoc/files/README_rdoc.html +133 -0
  39. data/rdoc/files/lib/svengali/config_rb.html +114 -0
  40. data/rdoc/files/lib/svengali/ext_string_rb.html +108 -0
  41. data/rdoc/files/lib/svengali/file_io_rb.html +115 -0
  42. data/rdoc/files/lib/svengali/machine_rb.html +108 -0
  43. data/rdoc/files/lib/svengali/platforms/debian_rb.html +107 -0
  44. data/rdoc/files/lib/svengali/platforms/default_rb.html +107 -0
  45. data/rdoc/files/lib/svengali/plugins/eucalyptus_rb.html +389 -0
  46. data/rdoc/files/lib/svengali/plugins/machine_config_rb.html +101 -0
  47. data/rdoc/files/lib/svengali/plugins/package_rb.html +101 -0
  48. data/rdoc/files/lib/svengali/ssh_rb.html +110 -0
  49. data/rdoc/files/lib/svengali/svengali_rb.html +125 -0
  50. data/rdoc/files/lib/svengali/util_rb.html +439 -0
  51. data/rdoc/files/lib/svengali_rb.html +108 -0
  52. data/rdoc/fr_class_index.html +37 -0
  53. data/rdoc/fr_file_index.html +41 -0
  54. data/rdoc/fr_method_index.html +100 -0
  55. data/rdoc/index.html +26 -0
  56. data/rdoc/rdoc-style.css +208 -0
  57. data/spec/spec.opts +1 -0
  58. data/spec/spec_helper.rb +9 -0
  59. data/spec/svengali_spec.rb +7 -0
  60. data/svengali.gemspec +113 -0
  61. data/svengali_sample.rb +43 -0
  62. data/test/scenario.sh +3 -0
  63. metadata +179 -0
@@ -0,0 +1,5 @@
1
+ #Debian
2
+
3
+ class Platform
4
+
5
+ end
@@ -0,0 +1,4 @@
1
+ #defualt platform: CentOS
2
+ class Platform
3
+
4
+ end
@@ -0,0 +1,339 @@
1
+ require 'timeout'
2
+ require "yaml"
3
+
4
+ # return -> symbol : one of values below
5
+ # :running, :pending, :shutdown, :terminated
6
+ def get_instance_state(instance_id_str)
7
+ exec_result = ""
8
+ while exec_result == ""
9
+ exec_result = `euca-describe-instances #{instance_id_str}`
10
+ end
11
+
12
+ if exec_result.index("pending")
13
+ return :pending
14
+ elsif exec_result.index("running")
15
+ return :running
16
+ elsif exec_result.index("shutting-down")
17
+ return :shutdown
18
+ elsif exec_result.index("terminated")
19
+ return :terminated
20
+ end
21
+ end
22
+
23
+ # return -> string: id of running instance
24
+ # this function..
25
+ # blocks until kicked image starts running
26
+ # uses c1.medium machine spec
27
+ def run_image(image_id_str)
28
+ begin
29
+ debug_p "trying kick instance from image #{image_id_str}"
30
+ instance_id = `euca-run-instances #{image_id_str} -t c1.medium`.scan(/\s+(i-\w+)\s+/)[0].to_s
31
+ rescue
32
+ debug_p "retry!"
33
+ retry
34
+ end
35
+
36
+ # waits until instance finishes booting
37
+ while(get_instance_state(instance_id) != :running)
38
+ end
39
+
40
+ debug_p "instance( #{instance_id} ) has been running successfully."
41
+
42
+ return instance_id
43
+ end
44
+
45
+ # this method blocks until the instance finishs terminating
46
+ def terminate_instance(instance_id_str)
47
+ `euca-terminate-instances #{instance_id_str}`
48
+
49
+ while(get_instance_state(instance_id_str) != :terminated)
50
+ end
51
+
52
+ debug_p "instance( #{instance_id_str} ) has been terminated successfully."
53
+ end
54
+
55
+ # this method blocks until the instance finishs terminating
56
+ def terminate_instance_all()
57
+ instance_id_arr = get_all_instance_id()
58
+
59
+ instance_id_arr.each{ |instance_id|
60
+ terminate_instance(instance_id)
61
+ }
62
+ end
63
+
64
+ # return -> array : like this
65
+ # ["i-xxxx","i-xxxx","i-xxxx",...]
66
+ def get_all_instance_id()
67
+ ret_arr = `euca-describe-instances`.scan(/\s+(i-\w+)\s+/)
68
+ debug_p ret_arr.inspect()
69
+ return ret_arr
70
+ end
71
+
72
+ # return -> string: image id
73
+ # when timeout, returns nil
74
+ def upload_and_register_image(image_path_str,timeout_sec = nil)
75
+ `euca-bundle-image -i #{image_path_str}`
76
+ dir_name = File::dirname(image_path_str)
77
+ if(dir_name == ".")
78
+ bucket_and_image_name = image_path_str.gsub("./","")
79
+ else
80
+ bucket_and_image_name = image_path_str.gsub(dir_name,"")
81
+ end
82
+
83
+ begin
84
+ timeout(timeout_sec) do
85
+ `euca-upload-bundle -b #{bucket_and_image_name} -m /tmp/#{bucket_and_image_name}.manifest.xml`
86
+ end
87
+ rescue TimeoutError
88
+ "Too long time elapsed to upload image file. It is highly possible that uploading is missed"
89
+ return nil
90
+ end
91
+
92
+ begin
93
+ image_id = `euca-register #{bucket_and_image_name}/#{bucket_and_image_name}.manifest.xml`.scan(/IMAGE\s+(emi\-\w+)\s*/)[0].to_s
94
+ rescue
95
+ debug_p "retry!"
96
+ retry
97
+ end
98
+
99
+ `rm -f /tmp/#{bucket_and_image_name}*`
100
+
101
+ debug_p "uploaded and registerd #{image_path_str}"
102
+ return image_id
103
+ end
104
+
105
+ # deregister specified image and delete images on server
106
+ def delete_image(image_id_str)
107
+ `euca-deregister #{image_id_str}`
108
+ bucket_and_image = get_bucket_and_image_name_by_id(image_id_str)
109
+
110
+ `euca-delete-bundle -b #{bucket_and_image[:bucket]} -p #{bucket_and_image[:image]} --clear`
111
+
112
+ debug_p "deregisterd and deleted #{image_id_str}"
113
+ end
114
+
115
+ # return -> {:bucket => string: name of bucket, :image => string: image name }
116
+ def get_bucket_and_image_name_by_id(image_id_str)
117
+ begin
118
+ bucket_and_image = `euca-describe-images #{image_id_str}`.scan(/^IMAGE\s+#{image_id_str}\s+(.+\.manifect\.xml)/)
119
+ rescue
120
+ debug_p "retry!"
121
+ retry
122
+ end
123
+
124
+ return {:bucket => bucket_and_image[0], :image => bucket_and_image[1]}
125
+ end
126
+ private :get_bucket_and_image_name_by_id
127
+
128
+ class Machine
129
+ @instance_id_str
130
+ @@do_cache = false
131
+
132
+ def set_instance_info(instance_id_str)
133
+ @instance_id_str = instance_id_str
134
+ end
135
+
136
+ # return -> string: ID of vm instance
137
+ def get_instance_info()
138
+ return @instance_id_str
139
+ end
140
+
141
+ def destroy_instance()
142
+ unless @instance_id_str
143
+ puts "set_cloud_info() should be called appropriately before destroying instance"
144
+ puts "exit destroy_instance() without terminating"
145
+ return
146
+ end
147
+
148
+ unless @@do_cache
149
+ terminate_instance(@instance_id_str)
150
+ end
151
+
152
+ end
153
+
154
+ # set whether cache and reuse guest instance on Eucalyptus
155
+ # if true value is set
156
+ # - destroy_instance(...) doesn't terminate instance
157
+ def set_whether_do_cache(true_or_false)
158
+ @@do_cache = true_or_false
159
+ end
160
+
161
+ end
162
+
163
+ class Cloud
164
+ # TODO: enabling lib to find newly booted node without pinging
165
+ DHCP_LEASE_RANGE = "xxx.xxx.xxx.xxx"
166
+
167
+ CACHE_FILE_NAME = "./machine_cache_hash.yml"
168
+
169
+ # whether cache and reuse guest instance on Eucalyptus
170
+ # default value is false
171
+ @@do_cache = false
172
+
173
+ @@default_user
174
+ @@default_pass
175
+
176
+ def self.Cloud(default_user,default_pass)
177
+ @@default_user = default_user
178
+ @@default_pass = default_pass
179
+ end
180
+
181
+ # return -> Machine : Machine instance applied network configuration and establised session
182
+ def self.get_a_machine_with_imageup(params_hash)
183
+ check_has_keys(params_hash,[:imagepath])
184
+
185
+ unless params_hash[:imageid] = upload_and_register_image(params_hash[image_path_str],120)
186
+ puts "uploading and registration of image failed"
187
+ err_message_and_exit("I wll exit")
188
+ end
189
+
190
+ not_tested()
191
+ return self.get_a_machine(params_hash)
192
+ end
193
+
194
+
195
+ # return -> Machine : Machine instance applied network configuration and establised session
196
+ def self.get_a_machine(params_hash)
197
+
198
+ # if @@do_cache true, Cloud class tries to reuse guest instance on Eucalyptus
199
+ # whether exist appropriate instace is checked in terms of IP address
200
+ if Cloud.is_exist_requested_machine(params_hash[:ipaddr]) && @@do_cache
201
+ debug_p "reused a guset instance which has address #{params_hash[:ipaddr]}"
202
+ # load instance ID corresponding to requested IP address from cache file
203
+ machine_cache_hash = Cloud.load_machine_cache_info()
204
+ instance_id = machine_cache_hash[params_hash[:ipaddr]]
205
+ else
206
+ # calling of this method isn't needed under normal conditions
207
+ get_ipaddr_of_instance_pre()
208
+
209
+ debug_p "executing euca-run-instance...."
210
+ # ** Attention ** below is draft code
211
+ instance_id = run_image(params_hash[:imageid])
212
+ debug_p "euca-run-instance finished."
213
+
214
+ #get a CLibIPAddr insance
215
+ ipaddr = get_ipaddr_of_instance(instance_id)
216
+ debug_p "IP address of the kicked instance: " + ipaddr.to_s
217
+
218
+ debug_p "configure network setting to the kicked instance."
219
+ vanilla_machine = Machine.new(ipaddr)
220
+ vanilla_machine.set_auth_info(DEFAULT_USER,DEFAULT_PASS)
221
+ vanilla_machine.establish_session()
222
+
223
+ vanilla_machine.config_nw_interface(:ipaddr => params_hash[:ipaddr], :interface => params_hash[:interface], :netmask => params_hash[:netmask], :gateway => params_hash[:gateway], :onboot => "yes")
224
+ vanilla_machine.set_resolver(:primary_ip => params_hash[:dns],:interface => params_hash[:interface])
225
+
226
+ #reloads network configuration
227
+ #10 seconds after, this will return with nil value
228
+ # TODO: should eliminate assumption for platform
229
+ debug_p "reload network configuration...."
230
+ puts vanilla_machine.exec!("/sbin/service network restart", 10)
231
+ debug_p "reloading of network configuration may have finished."
232
+
233
+ # write machine info to cache file
234
+ if @@do_cache
235
+ machine_cache_hash = Cloud.load_machine_cache_info()
236
+ debug_p "----------------loaded_hash------------------"
237
+ debug_p machine_cache_hash.inspect()
238
+ debug_p "class name of machine_cache_hash is #{machine_cache_hash.class}"
239
+ debug_p "---------------------------------------------"
240
+ machine_cache_hash[params_hash[:ipaddr]] = instance_id
241
+ Cloud.dump_machine_cache_info(machine_cache_hash)
242
+ end
243
+
244
+ end
245
+
246
+ configured_machine = Machine.new(params_hash[:ipaddr])
247
+ configured_machine.set_auth_info(DEFAULT_USER,DEFAULT_PASS)
248
+ configured_machine.establish_session()
249
+ configured_machine.set_instance_info(instance_id)
250
+
251
+ if @@do_cache
252
+ configured_machine.set_whether_do_cache(true)
253
+ end
254
+
255
+ return configured_machine
256
+ end
257
+
258
+ # ipaddr -> CLibIPAddr
259
+ # whether exist appropriate instace is checked in terms of IP address
260
+ def self.is_exist_requested_machine(ipaddr)
261
+ return is_exist_by_ping(ipaddr)
262
+ end
263
+
264
+ # ** Attention ** this is quick-fix implementation
265
+ # this method can't work on parallel kicking
266
+ #
267
+ # return -> CLibIPAddr : xxx
268
+ def self.get_ipaddr_of_instance(instance_id)
269
+ unless @@pre_alived_hash
270
+ err_message_and_exit("get_ipaddr_of_instance_pre() should be called on the eve of run_image(...)")
271
+ end
272
+
273
+ debug_p @@pre_alived_hash.inspect()
274
+
275
+ while(true)
276
+ alived_hash = find_machines_on_range_by_ping(DHCP_LEASE_RANGE)
277
+
278
+ # find difference
279
+ alived_hash.delete_if{ |key,value| @@pre_alived_hash.has_key?(key)}
280
+
281
+ if alived_hash.size == 1
282
+ debug_p alived_hash.inspect()
283
+ ret = alived_hash.shift()[0]
284
+ debug_p "found #{ret}"
285
+ return CLibIPAddr.new(ret)
286
+ elsif alived_hash.size > 1
287
+ err_message_and_exit("There may be other booting machine!")
288
+ end
289
+ sleep 1 #leave a space
290
+ end
291
+
292
+ end
293
+
294
+ # call of this method isn't needed under normal conditions
295
+ # this method should be called on the eve of run_image(...)
296
+ def self.get_ipaddr_of_instance_pre()
297
+ @@pre_alived_hash = find_machines_on_range_by_ping(DHCP_LEASE_RANGE)
298
+ end
299
+
300
+ # set whether cache and reuse guest instance on Eucalyptus
301
+ # if true value is set
302
+ # - get_a_machine(...) tries to reuse guest instance on Eucalyptus
303
+ # - destroy_instance(...) of Machine class doesn't terminate instance
304
+ # - write kicked machine info to cache file
305
+ def self.set_whether_do_cache(true_or_false)
306
+ @@do_cache = true_or_false
307
+ end
308
+
309
+ # machine_cache_hash -> hash : {"xxx.xxx.xxx.xxx" => "i-xxxxxxx", ... }
310
+ def self.dump_machine_cache_info(machine_cache_hash)
311
+ file = open(CACHE_FILE_NAME,"w")
312
+ YAML.dump(machine_cache_hash,file)
313
+ file.close()
314
+ end
315
+
316
+ # return -> hash: {"xxx.xxx.xxx.xxx" => "i-xxxxxxx", ... }
317
+ # if chache file doesn't exist, return a empty hash
318
+ def self.load_machine_cache_info()
319
+ if File.exist?(CACHE_FILE_NAME)
320
+ ret_hash = nil
321
+ open(CACHE_FILE_NAME){ |file|
322
+ ret_hash = YAML.load(file)
323
+ }
324
+
325
+ return ret_hash
326
+ else
327
+ return Hash.new()
328
+ end
329
+ end
330
+
331
+ end
332
+
333
+
334
+ # check source_certificate.sh has executed correctly
335
+ unless ENV["EC2_URL"]
336
+ puts "ERROR: please run command below before use this library with eucalyptus plugin!!\n \"source ./utility_scripts/source_certificate.sh\"\n"
337
+ exit()
338
+ end
339
+
@@ -0,0 +1,126 @@
1
+ class Machine
2
+
3
+ # :ipaddr -> CLibIPAddr : IP address which assigned to interface
4
+ # :interface -> string : interface name
5
+ # :netmask -> string : netmask
6
+ # :gateway -> CLibIPAddr : IP address of gateway
7
+ # :onboot -> string : yes or no (you can omit)
8
+ # :hwaddr -> string : MAC address (you can omit)
9
+ def config_nw_interface(params_hash)
10
+ config_file = nil
11
+ if interface_name_str = params_hash[:interface]
12
+ #open or create target file
13
+ target_path = ExtStr.path["network_configs"]+"ifcfg-" + interface_name_str
14
+ config_file = self.get_config_file(target_path)
15
+ else
16
+ err_message_and_exit("please specify a value of :interface!")
17
+ end
18
+
19
+ if netmask = params_hash[:netmask]
20
+ netmask_str = netmask.to_s()
21
+ # remove_col_by_regexp should be used under normal condition
22
+ config_file.remove_col_by_str("NETMASK")
23
+ config_file.append_str("NETMASK=" + netmask_str + "\n")
24
+ else
25
+ err_message_and_exit("please specify a value of :netmask!")
26
+ end
27
+
28
+ if ipaddr = params_hash[:ipaddr]
29
+ ipaddr_str = ipaddr.to_s()
30
+ # remove_col_by_regexp should be used under normal condition
31
+ config_file.remove_col_by_str("IPADDR")
32
+ config_file.append_str("IPADDR=" + ipaddr_str + "\n")
33
+ else
34
+ err_message_and_exit("please specify a value of :ipaddr!")
35
+ end
36
+
37
+ if gateway = params_hash[:gateway]
38
+ gateway_str = gateway.to_s()
39
+ # remove_col_by_regexp should be used under normal condition
40
+ config_file.remove_col_by_str("GATEWAY")
41
+ config_file.append_str("GATEWAY=" + gateway_str + "\n")
42
+ else
43
+ err_message_and_exit("please specify a value of :gateway!")
44
+ end
45
+
46
+ if hwaddr = params_hash[:hwaddr]
47
+ # remove_col_by_regexp should be used under normal condition
48
+ config_file.remove_col_by_str("HWADDR")
49
+ config_file.append_str("HWADDR=" + hwaddr + "\n")
50
+ end
51
+
52
+ onboot = params_hash[:onboot] || "yes" # default is "yes"
53
+ # remove_col_by_regexp should be used under normal condition
54
+ config_file.remove_col_by_str("ONBOOT")
55
+ config_file.append_str("ONBOOT=" + onboot + "\n")
56
+
57
+ config_file.remove_col_by_str("BOOTPROTO")
58
+ config_file.append_str("BOOTRPROTO=static\n")
59
+
60
+ config_file.save()
61
+ lazy_inp()
62
+ end
63
+
64
+ # !!!! Now, this method write resolver information !!!!
65
+ # !!!! to /etc/sysconfig/network-scripts/ifcfg-ethX !!!!
66
+ # !!!! due to baffling behavior of CentOS !!!!
67
+ #
68
+ # :primary_ip -> CLibIPAddr : IP address of primary DNS
69
+ # :secondry_ip -> CLibIPAddr : IP address of secondly DNS
70
+ # :search_domain -> string : domain of search directive
71
+ #
72
+ # :interface -> string : interface name (for CentOS)
73
+ def set_resolver(params_hash)
74
+ #open or create target file
75
+ config_file = nil
76
+ if interface_name_str = params_hash[:interface]
77
+ target_path = ExtStr.path["network_configs"]+"ifcfg-" + interface_name_str
78
+ config_file = self.get_config_file(target_path)
79
+ else
80
+ err_message_and_exit("please specify a value of :interface!")
81
+ end
82
+
83
+
84
+ # target_path = ExtStr.path["resolver_config"]
85
+ # config_file = self.get_config_file(target_path)
86
+ #
87
+ # if search_domain = params_hash[:search_domain]
88
+ # # remove_col_by_regexp should be used under normal condition
89
+ # config_file.append_str("search " + search_domain + "\n")
90
+ # end
91
+ #
92
+ # if primary_ip = params_hash[:primary_ip]
93
+ # primary_ip_str = primary_ip.to_s()
94
+ # # remove_col_by_regexp should be used under normal condition
95
+ # config_file.remove_col_by_str("nameserver")
96
+ # config_file.append_str("nameserver " + primary_ip_str + "\n")
97
+ # else
98
+ # err_message_and_exit("please specify a value of :primary_ip!")
99
+ # end
100
+ #
101
+ # if secondly_ip = params_hash[:secondly_ip]
102
+ # secondly_ip_str = secondly_ip.to_s()
103
+ # # remove_col_by_regexp should be used under normal condition
104
+ # config_file.append_str("nameserver " + secondly_ip_str + "\n")
105
+ # end
106
+
107
+
108
+ if primary_ip = params_hash[:primary_ip]
109
+ primary_ip_str = primary_ip.to_s()
110
+ # remove_col_by_regexp should be used under normal condition
111
+ config_file.remove_col_by_str("PEERDNS")
112
+ config_file.append_str("PEERDNS=yes\n")
113
+
114
+ config_file.remove_col_by_str("DNS1")
115
+ config_file.append_str("DNS1=" + primary_ip_str + "\n")
116
+ else
117
+ err_message_and_exit("please specify a value of :primary_ip!")
118
+ end
119
+
120
+ config_file.save()
121
+
122
+ lazy_inp()
123
+ end
124
+
125
+ end
126
+