brpm_content_framework 0.1.55

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +38 -0
  3. data/.travis.yml +17 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +21 -0
  6. data/README.md +308 -0
  7. data/Rakefile +23 -0
  8. data/TO_BE_MIGRATED.txt +9 -0
  9. data/architecture.png +0 -0
  10. data/automations/direct_execute.meta +10 -0
  11. data/automations/direct_execute.rb +10 -0
  12. data/automations/install_module.meta +10 -0
  13. data/automations/install_module.rb +13 -0
  14. data/bin/brpm_install +30 -0
  15. data/bin/brpm_uninstall +30 -0
  16. data/bin/event_handler +63 -0
  17. data/bin/webhook_receiver +49 -0
  18. data/brpm_content.gemspec +31 -0
  19. data/config.yml +8 -0
  20. data/infrastructure/.bashrc +6 -0
  21. data/infrastructure/.brpm +2 -0
  22. data/infrastructure/config/customer_include.rb +26 -0
  23. data/infrastructure/config/server.yml +3 -0
  24. data/infrastructure/log.html +39 -0
  25. data/infrastructure/scripts/backup_database.sh +19 -0
  26. data/infrastructure/scripts/ddns.sh +10 -0
  27. data/infrastructure/scripts/install_brpm.sh +63 -0
  28. data/infrastructure/scripts/maintenance.sh +4 -0
  29. data/infrastructure/scripts/patch_brpm.sh +90 -0
  30. data/infrastructure/scripts/restore_database.sh +33 -0
  31. data/infrastructure/scripts/run_event_handler.cmd +19 -0
  32. data/infrastructure/scripts/run_event_handler.sh +20 -0
  33. data/infrastructure/scripts/run_webhook_receiver.cmd +15 -0
  34. data/infrastructure/scripts/run_webhook_receiver.sh +15 -0
  35. data/infrastructure/silent_install_options_4.6.txt +93 -0
  36. data/infrastructure/silent_install_options_upgrade_4.6.txt +92 -0
  37. data/infrastructure/smtp_settings.rb +42 -0
  38. data/lib/brpm_auto.rb +358 -0
  39. data/lib/brpm_script_executor.rb +80 -0
  40. data/lib/logging/brpm_logger.rb +39 -0
  41. data/lib/logging/logger_base.rb +36 -0
  42. data/lib/logging/simple_logger.rb +27 -0
  43. data/lib/module_installer.rb +483 -0
  44. data/lib/params/all_params.rb +80 -0
  45. data/lib/params/integration_settings.rb +27 -0
  46. data/lib/params/params.rb +174 -0
  47. data/lib/params/params_base.rb +81 -0
  48. data/lib/params/request_params.rb +38 -0
  49. data/lib/rest_api.rb +155 -0
  50. data/lib/semaphore.rb +79 -0
  51. data/lib/utilities.rb +317 -0
  52. data/lib/version_control/git.rb +192 -0
  53. data/lib/version_control/svn.rb +221 -0
  54. data/lib/write_to.rb +1 -0
  55. data/tests/all_params_spec.rb +116 -0
  56. data/tests/brpm_auto_spec.rb +84 -0
  57. data/tests/customer_include/config/customer_include.rb +10 -0
  58. data/tests/customer_include/config/server.yml +3 -0
  59. data/tests/customer_include_spec.rb +29 -0
  60. data/tests/gemspec_spec.rb +11 -0
  61. data/tests/module_installer_spec.rb +46 -0
  62. data/tests/params_spec.rb +172 -0
  63. data/tests/request_params_spec.rb +86 -0
  64. data/tests/server_yaml_spec.rb +19 -0
  65. data/tests/spec_helper.rb +64 -0
  66. data/to_be_migrated/brpm_framework.rb +88 -0
  67. data/to_be_migrated/customer_include_default.rb +25 -0
  68. data/to_be_migrated/local_jirb.rb +15 -0
  69. data/to_be_migrated/resource_framework.rb +211 -0
  70. data/transport/dispatch_baa.rb +355 -0
  71. data/transport/dispatch_base.rb +345 -0
  72. data/transport/dispatch_nsh.rb +248 -0
  73. data/transport/dispatch_ssh.rb +154 -0
  74. data/transport/transport_baa.rb +1095 -0
  75. data/transport/transport_nsh.rb +359 -0
  76. data/transport/transport_ssh.rb +220 -0
  77. metadata +204 -0
@@ -0,0 +1,345 @@
1
+ # dispatch_base.rb
2
+ # Module for action dispatch common methods
3
+ require 'digest/md5'
4
+
5
+ DEFAULT_PARAMS_FILTER = "ENV_" if !defined?(DEFAULT_PARAMS_FILTER)
6
+ STANDARD_PROPERTIES = ["SS_application", "SS_component", "SS_environment", "SS_component_version", "SS_request_number"]
7
+ OS_PLATFORMS = {
8
+ "win" => {"name" => "Windows", "tmp_dir" => "/C/Windows/temp"},
9
+ "nix" => {"name" => "Unix", "tmp_dir" => "/tmp"},
10
+ "nux" => {"name" => "Linux", "tmp_dir" => "/tmp"}}
11
+
12
+
13
+ class DispatchBase
14
+ # Initialize the class
15
+ #
16
+ # ==== Attributes
17
+ #
18
+ # * +options+ - hash of options to use, send "output_file" to point to the logging file
19
+ # * +test_mode+ - true/false to simulate commands instead of running them
20
+ #
21
+ def initialize(options = {}, compat_options = {})
22
+ self.extend Utilities
23
+ if options.has_key?("SS_output_dir")
24
+ BrpmAuto.log "Load for this class has changed, no longer necessary to send params as 1st argument"
25
+ options = compat_options
26
+ end
27
+ @verbose = get_option(options, "verbose", false)
28
+ @output_dir = BrpmAuto.params.output_dir
29
+ end
30
+
31
+ # Builds a hash of properties to transfer to target
32
+ #
33
+ # ==== Attributes
34
+ #
35
+ # * +keyword_filter+ - filter for params (param selected if filter included in key)
36
+ # * +strip_filter+ - removes filter text from resulting key
37
+ # ==== Returns
38
+ #
39
+ # hash of properties to transfer
40
+ #
41
+ def get_transfer_properties(keyword_filter = DEFAULT_PARAMS_FILTER, strip_filter = true)
42
+ result = {}
43
+ STANDARD_PROPERTIES.each{|prop| result[prop.gsub("SS_","RPM_")] = BrpmAuto.params[prop] }
44
+ BrpmAuto.params.each{|k,v| result[strip_filter ? k.gsub(keyword_filter,"") : k] = v if k.include?(keyword_filter) }
45
+ result
46
+ end
47
+
48
+ # Add BRPD-like params to transfer_properties
49
+ #
50
+ # ==== Attributes
51
+ #
52
+ # * +props+ - the existing transfer properties hash
53
+ # * +payload_path+ - the path for any previously delivered content
54
+ # * +target_dir+ - the delivery directory on the target
55
+ # ==== Returns
56
+ #
57
+ # nothing - modifies passed property hash
58
+ #
59
+ def brpd_compatibility(props, payload_path = nil, servers = nil)
60
+ props["VL_CONTENT_PATH"] = payload_path if payload_path
61
+ props["VL_CONTENT_NAME"] = File.basename(payload_path) if payload_path
62
+ props["VL_CHANNEL_ROOT"] = props["RPM_CHANNEL_ROOT"]
63
+ props["VL_DISPATCH_TARGET_HOST"] = servers.nil? ? get_server_list.keys[0] : servers.first[0]
64
+ end
65
+
66
+ # Add server properties to transfer properties
67
+ #
68
+ # ==== Attributes
69
+ #
70
+ # * +props+ - the existing transfer properties hash
71
+ # * +servers+ - hash of server properties
72
+ # * +os_platform+ - os platform
73
+ # ==== Returns
74
+ #
75
+ # nothing - modifies passed property hash
76
+ #
77
+ def add_channel_properties(props, servers, os_platform = "win")
78
+ s_props = servers.first[1]
79
+ base_dir = s_props["CHANNEL_ROOT"] if s_props.has_key?("CHANNEL_ROOT")
80
+ base_dir ||= s_props["base_dir"] if s_props.has_key?("base_dir")
81
+ base_dir ||= OS_PLATFORMS[os_platform]["tmp_dir"]
82
+ props["RPM_CHANNEL_ROOT"] = base_dir
83
+ end
84
+
85
+ # Removes carriage returns for unix compatibility
86
+ # Opens passed script path, modifies and saves file
87
+ # ==== Attributes
88
+ #
89
+ # * +os_platform+ - os platform
90
+ # * +script_file+ - path to script to modify
91
+ # * +contents+ - optional - if passed will replace the content in script_file
92
+ # ==== Returns
93
+ #
94
+ # path to modified script
95
+ #
96
+ def clean_line_breaks(os_platform, script_file, contents = nil)
97
+ return if os_platform =~ /win/
98
+ contents = File.open(script_file).read if contents.nil?
99
+ fil = File.open(script_file,"w+")
100
+ fil.puts contents.gsub("\r", "")
101
+ fil.flush
102
+ fil.close
103
+ script_file
104
+ end
105
+
106
+ # Creates a temp file in output dir
107
+ # returns path to temp file
108
+ # ==== Attributes
109
+ #
110
+ # * +content+ - content for file
111
+ # * +options+ - hash of options, includes ext to force the file extension e.g. {"ext" => ".sql"}
112
+ # ==== Returns
113
+ #
114
+ # path to file
115
+ #
116
+ def make_temp_file(content, platform = "linux", options = {})
117
+ ext = get_option(options, "ext")
118
+ if ext == ""
119
+ ext = platform.downcase == "linux" ? ".sh" : ".bat"
120
+ end
121
+ file_path = File.join(BrpmAuto.params["SS_output_dir"],"shell_#{precision_timestamp}#{ext}")
122
+ fil = File.open(file_path, "w+")
123
+ fil.puts content
124
+ fil.flush
125
+ fil.close
126
+ file_path
127
+ end
128
+
129
+ # Builds the wrapper script for the target
130
+ # sets environment variables and call to run target script
131
+ # follows platform directives or shebang information
132
+ #
133
+ # ==== Attributes
134
+ #
135
+ # * +os_platform+ - os platform
136
+ # * +shebang+ - hash of processed shebang
137
+ # * +properties+ - hash of properties to become environment variables
138
+ # * +options+ - hash of optionss, includes script_target - what the wrapper will call
139
+ # ==== Returns
140
+ #
141
+ # path to wrapper script
142
+ #
143
+ def build_wrapper_script(os_platform, shebang, properties, options = {})
144
+ msg = "Environment variables from BRPM"
145
+ wrapper = "srun_wrapper_#{precision_timestamp}"
146
+ alt_target = get_option(options,"script_target")
147
+ cmd = shebang["cmd"]
148
+ target = alt_target == "" ? File.basename(get_param("SS_script_file")) : alt_target
149
+ cmd = cmd.gsub("%%", target) if shebang["cmd"].end_with?("%%")
150
+ cmd = "#{cmd} #{target}" unless shebang["cmd"].end_with?("%%")
151
+ if os_platform =~ /win/
152
+ properties["RPM_CHANNEL_ROOT"] = dos_path(properties["RPM_CHANNEL_ROOT"])
153
+ properties["VL_CHANNEL_ROOT"] = properties["RPM_CHANNEL_ROOT"]
154
+ wrapper = "#{wrapper}.bat"
155
+ script = "@echo off\r\necho |hostname > junk.txt\r\nset /p HOST=<junk.txt\r\necho y|del junk.txt\r\n"
156
+ script += "echo ============== HOSTNAME: %HOST% ==============\r\n"
157
+ script += "echo #{msg} \r\n"
158
+ properties.each{|k,v| script += "set #{k}=#{v}\r\n" }
159
+ script += "echo Execute the file\r\n"
160
+ script += "cd %RPM_CHANNEL_ROOT%\r\n"
161
+ script += "#{cmd}\r\n"
162
+ script += "echo EXIT_CODE: %errorlevel%\r\n"
163
+ script += "timeout /t <5> /nobreak\r\n"
164
+ script += "echo y|del #{target}\r\n"
165
+ else
166
+ wrapper = "#{wrapper}.sh"
167
+ script = "echo \"============== HOSTNAME: `hostname` ==============\"\n"
168
+ script += "echo #{msg} \n"
169
+ properties.each{|k,v| script += "export #{k}=\"#{v}\"\n" }
170
+ script += "echo Execute the file\n"
171
+ script += "cd $RPM_CHANNEL_ROOT\n"
172
+ script += "#{cmd}\n"
173
+ script += "echo EXIT_CODE: $?\n"
174
+ script += "sleep 2\nrm -f #{target}"
175
+ end
176
+ fil = File.open(File.join(@output_dir, wrapper),"w+")
177
+ fil.puts script
178
+ fil.flush
179
+ fil.close
180
+ File.join(@output_dir, wrapper)
181
+ end
182
+
183
+ # Builds the wrapper script for a single command
184
+ #
185
+ # ==== Attributes
186
+ #
187
+ # * +command+ - command to execute e.g. unzip
188
+ # * +os_platform+ - os platform
189
+ # * +source_path+ - path to source file (local)
190
+ # * +target_path+ - destination path on target server
191
+ # ==== Returns
192
+ #
193
+ # path to wrapper script
194
+ #
195
+ def create_command_wrapper(command, os_platform, source_path, target_path)
196
+ msg = "Environment variables from BRPM"
197
+ wrapper = "srun_wrapper_#{precision_timestamp}"
198
+ target = File.basename(source_path)
199
+ if os_platform =~ /win/
200
+ target_path = dos_path(target_path)
201
+ wrapper = "#{wrapper}.bat"
202
+ script = "@echo off\r\necho |hostname > junk.txt\r\nset /p HOST=<junk.txt\r\necho y | del junk.txt\r\n"
203
+ script += "echo ============== HOSTNAME: %HOST% ==============\r\n"
204
+ script += "echo #{msg} \r\n"
205
+ script += "set RPM_CHANNEL_ROOT=#{target_path}\r\n"
206
+ script += "echo Execute the file\r\n"
207
+ script += "cd %RPM_CHANNEL_ROOT%\r\n"
208
+ script += "#{command} #{target}\r\n"
209
+ script += "echo EXIT_CODE: %errorlevel%\r\n"
210
+ script += "timeout /t <5> /nobreak\r\n"
211
+ script += "echo y|del #{target}\r\n"
212
+ else
213
+ wrapper = "#{wrapper}.sh"
214
+ script = "echo \"============== HOSTNAME: `hostname` ==============\"\n"
215
+ script += "echo #{msg} \n"
216
+ script += "export RPM_CHANNEL_ROOT=\"#{target_path}\"\n"
217
+ script += "echo Execute the file\n"
218
+ script += "cd $RPM_CHANNEL_ROOT\n"
219
+ script += "#{command} #{target}\n"
220
+ script += "echo EXIT_CODE: $?\n"
221
+ script += "sleep 2\nrm -f #{target}"
222
+ end
223
+ fil = File.open(File.join(@output_dir, wrapper),"w+")
224
+ fil.puts script
225
+ fil.flush
226
+ fil.close
227
+ File.join(@output_dir, wrapper)
228
+ end
229
+
230
+ # Builds the list of files for deployment
231
+ # assumes that there are 3 sources: version, path entry and uploads
232
+ # ==== Attributes
233
+ #
234
+ # * +p_obj+ - a handle to the current params object
235
+ # * +options+ - hash of options including:
236
+ #
237
+ # ==== Returns
238
+ #
239
+ # array of nsh paths
240
+ #
241
+ def get_artifact_paths(p_obj, options = {})
242
+ files_to_deploy = []
243
+ artifact_path = p_obj.get("step_version_artifact_url", nil)
244
+ artifact_paths = p_obj.split_nsh_path(artifact_path) unless artifact_path.nil?
245
+ path_server = artifact_path.nil? ? "" : artifact_paths[0]
246
+ version = p_obj.get("step_version")
247
+ staging_server = p_obj.get("staging_server", path_server)
248
+ brpm_hostname = p_obj.get("SS_base_url").gsub(/^.*\:\/\//, "").gsub(/\:\d.*/, "")
249
+ files_to_deploy << p_obj.get_attachment_nsh_path(brpm_hostname, p_obj.get("Upload Action File")) unless p_obj.get("Upload Action File") == ""
250
+ files_to_deploy << p_obj.get_attachment_nsh_path(brpm_hostname, p_obj.uploadfile_1) unless p_obj.uploadfile_1 == ""
251
+ files_to_deploy << p_obj.get_attachment_nsh_path(brpm_hostname, p_obj.uploadfile_2) unless p_obj.uploadfile_2 == ""
252
+ entered_paths = p_obj.get("nsh_paths", p_obj.get("artifact_paths"))
253
+ if entered_paths != ""
254
+ staging_server = "none"
255
+ entered_paths.split(',').each do |path|
256
+ ans = p_obj.split_nsh_path(path)
257
+ staging_server = ans[0] if ans[0].length > 2
258
+ files_to_deploy << "//#{staging_server}#{ans[1].strip}" if ans[1].length > 2
259
+ end
260
+ end
261
+ unless artifact_path.nil?
262
+ staging_server = "none"
263
+ staging_server = artifact_paths[0] if artifact_paths[0].length > 2
264
+ if artifact_path.start_with?("//")
265
+ artifact_paths[1].split(',').each do |path|
266
+ staging = staging_server
267
+ ans = p_obj.split_nsh_path(path)
268
+ staging = ans[0] if ans[0].length > 2
269
+ files_to_deploy << "//#{staging}#{ans[1].strip}" if ans[1].length > 2
270
+ end
271
+ else
272
+ artifact_paths[1].split(',').each do |path|
273
+ files_to_deploy << path
274
+ end
275
+ end
276
+ end
277
+ files_to_deploy
278
+ end
279
+
280
+ # Packages files from local staging directory
281
+ #
282
+ # ==== Attributes
283
+ #
284
+ # * +staging_path+ - path to files
285
+ # * +version+ - version to assign
286
+ # ==== Returns
287
+ #
288
+ # hash of instance_path and md5 - {"instance_path" => "", "md5" => ""}
289
+ def package_staged_artifacts(staging_path, version)
290
+ package_file = "package_#{version}.zip"
291
+ instance_path = File.join(staging_path, package_file)
292
+ staging_artifacts = Dir.entries(staging_path).reject{|k| [".",".."].include?(k) }
293
+ return {"instance_path" => "ERROR - no files in staging area", "md5" => ""} if staging_artifacts.size < 1
294
+ cmd = "cd #{staging_path} && zip -r #{package_file} *" unless Windows
295
+ result = execute_shell(cmd)
296
+ md5 = Digest::MD5.file(instance_path).hexdigest
297
+ {"instance_path" => instance_path, "md5" => md5, "manifest" => staging_artifacts}
298
+ end
299
+
300
+ # Return the name or dns of servers in a hash list
301
+ # if dns exists, uses that, otherwise, name
302
+ # ==== Attributes
303
+ #
304
+ # * +servers+ - standard servers hash
305
+ # ==== Returns
306
+ #
307
+ # * array of server dns's
308
+ #
309
+ def server_dns_names(servers)
310
+ result = []
311
+ servers.each do |name,props|
312
+ if props["dns"].length < 3 || props["dns"].start_with?("http")
313
+ result << name
314
+ else
315
+ result << props["dns"]
316
+ end
317
+ end
318
+ result
319
+ end
320
+
321
+ # Returns the short name for the os platform
322
+ # Send the OS
323
+ def os_platform(platform, abbrev = true)
324
+ result = "nux"
325
+ result = "nix" if platform.downcase =~ /nix/
326
+ result = "win" if platform.downcase =~ /win/
327
+ result = {"nux" => "unix", "nix" => "linux", "win" => "windows"}[result] unless abbrev
328
+ result
329
+ end
330
+
331
+ # Returns plaform information about the first server assigned
332
+ # (works on teh assumption that all assigned servers are similar!)
333
+ # ==== Returns
334
+ #
335
+ # * hash of server information {"server", "os", "channel_root"}
336
+ #
337
+ def lead_server_info
338
+ servers = BrpmAuto.params.servers
339
+ cur = servers.keys.first
340
+ os = os_platform(servers[cur]["os_platform"], false)
341
+ channel_root = servers[cur].has_key?("CHANNEL_ROOT") ? servers[cur]["CHANNEL_ROOT"] : (os == "windows" ? "C:\\temp" : "/tmp")
342
+ server_info = {"server" => cur, "os" => os, "channel_root" => channel_root}
343
+ end
344
+
345
+ end
@@ -0,0 +1,248 @@
1
+ # dispatch_srun.rb
2
+ # Module for action dispatch with nsh protocol
3
+ libDir = File.expand_path(File.dirname(__FILE__))
4
+ require "#{libDir}/dispatch_base"
5
+
6
+
7
+ class DispatchNSH < DispatchBase
8
+ # Initialize the class
9
+ #
10
+ # ==== Attributes
11
+ #
12
+ # * +nsh_object+ - handle to an NSH object
13
+ # * +options+ - hash of options to use, send "output_file" to point to the logging file
14
+ # * +test_mode+ - true/false to simulate commands instead of running them
15
+ #
16
+ def initialize(nsh_object, options = {}, compat_options = {})
17
+ self.extend Utilities
18
+ if options.has_key?("SS_output_dir")
19
+ BrpmAuto.log "Load for this class has changed, no longer necessary to send params as 2nd argument"
20
+ options = compat_options
21
+ end
22
+ @nsh = nsh_object
23
+ @verbose = get_option(options, "verbose", false)
24
+ @output_dir = BrpmAuto.params["SS_output_dir"]
25
+ end
26
+
27
+ # Wrapper to run a shell action
28
+ # opens passed script path, or executes passed text
29
+ # processes the script in erb first to allow param substitution
30
+ # note script may have keyword directives (see additional docs)
31
+ # ==== Attributes
32
+ #
33
+ # * +script_file+ - the path to the script or the text of the script
34
+ # * +options+ - hash of options, includes:
35
+ # * +-servers to override step servers
36
+ # * +-transfer_properties - the properties to push to the wrapper script
37
+ # * +-transfer_prefix - prefix to grab transfer properties from params
38
+ #
39
+ # ==== Returns
40
+ #
41
+ # action output
42
+ #
43
+ def execute_script(script_file, options = {})
44
+ # get the body of the action
45
+ content = File.open(script_file).read
46
+ seed_servers = get_option(options, "servers")
47
+ loop_servers = get_option(options, "each_server")
48
+ transfer_properties = get_option(options, "transfer_properties",{})
49
+ keyword_items = get_keyword_items(content)
50
+ params_filter = get_option(keyword_items, "RPM_PARAMS_FILTER")
51
+ params_filter = get_option(options, "transfer_prefix", DEFAULT_PARAMS_FILTER)
52
+ transfer_properties.merge!(get_transfer_properties(params_filter, strip_prefix = true))
53
+ BrpmAuto.log "#----------- Executing Script on Remote Hosts -----------------#"
54
+ BrpmAuto.log "# Script: #{script_file}"
55
+ result = "No servers to execute on"
56
+ # Loop through the platforms
57
+ OS_PLATFORMS.each do |os, os_details|
58
+ servers = BrpmAuto.params.get_servers_by_os_platform(os) if seed_servers == ""
59
+ servers = BrpmAuto.params.get_servers_by_os_platform(os, seed_servers) if seed_servers != ""
60
+ BrpmAuto.message_box "OS Platform: #{os_details["name"]}"
61
+ BrpmAuto.log "No servers selected for: #{os_details["name"]}" if servers.size == 0
62
+ next if servers.size == 0
63
+ BrpmAuto.log "# #{os_details["name"]} - Targets: #{servers.inspect}"
64
+ BrpmAuto.log "# Setting Properties:"
65
+ add_channel_properties(transfer_properties, servers, os)
66
+ brpd_compatibility(transfer_properties, nil, servers)
67
+ transfer_properties.each{|k,v| BrpmAuto.log "\t#{k} => #{v}" }
68
+ shebang = read_shebang(os, content)
69
+ BrpmAuto.log "Shebang: #{shebang.inspect}"
70
+ wrapper_path = build_wrapper_script(os, shebang, transfer_properties, {"script_target" => File.basename(script_file)})
71
+ BrpmAuto.log "# Wrapper: #{wrapper_path}"
72
+ target_path = @nsh.nsh_path(transfer_properties["RPM_CHANNEL_ROOT"])
73
+ BrpmAuto.log "# Copying script to target: "
74
+ clean_line_breaks(os, script_file, content)
75
+ result = @nsh.ncp(server_dns_names(servers), script_file, target_path)
76
+ BrpmAuto.log result
77
+ BrpmAuto.log "# Executing script on target via wrapper:"
78
+ result = @nsh.script_exec(server_dns_names(servers), wrapper_path, target_path)
79
+ BrpmAuto.log result
80
+ end
81
+ result
82
+ end
83
+
84
+ # Wrapper to run a shell action
85
+ # opens passed script path, or executes passed text
86
+ # processes the script in erb first to allow param substitution
87
+ # this method will separately resolve each server properties and execute in sequence
88
+ # note script may have keyword directives (see additional docs)
89
+ # ==== Attributes
90
+ #
91
+ # * +script_file+ - the path to the script or the text of the script
92
+ # * +options+ - hash of options, includes:
93
+ # * +-servers to override step servers
94
+ # * +-transfer_properties - the properties to push to the wrapper script
95
+ # * +-transfer_prefix - prefix to grab transfer properties from params
96
+ # * +-strip_prefix - remove the prefix or leave it (true/false)
97
+ #
98
+ # ==== Returns
99
+ #
100
+ # action output
101
+ #
102
+ def execute_script_per_server(script_file, options = {})
103
+ # get the body of the action
104
+ content = File.open(script_file).read
105
+ seed_servers = get_option(options, "servers")
106
+ transfer_properties = get_option(options, "transfer_properties",{})
107
+ keyword_items = get_keyword_items(content)
108
+ params_filter = get_option(keyword_items, "RPM_PARAMS_FILTER")
109
+ params_filter = get_option(options, "transfer_prefix", DEFAULT_PARAMS_FILTER)
110
+ strip_prefix = get_option(options, "strip_prefix", true)
111
+ transfer_properties.merge!(get_transfer_properties(params_filter, strip_prefix))
112
+ BrpmAuto.log "#----------- Executing Script on Remote Hosts -----------------#"
113
+ BrpmAuto.log "# Script: #{script_file}"
114
+ result = "No servers to execute on"
115
+ grouped_result = []
116
+ # Loop through the platforms
117
+ OS_PLATFORMS.each do |os, os_details|
118
+ servers_list = BrpmAuto.params.get_servers_by_os_platform(os) if seed_servers == ""
119
+ servers_list = BrpmAuto.params.get_servers_by_os_platform(os, seed_servers) if seed_servers != ""
120
+ BrpmAuto.message_box "OS Platform: #{os_details["name"]}"
121
+ BrpmAuto.log "No servers selected for: #{os_details["name"]}" if servers_list.size == 0
122
+ next if servers_list.size == 0
123
+ BrpmAuto.log "# #{os_details["name"]} - Targets: #{servers_list.inspect}"
124
+ servers_list.each do |item|
125
+ servers = {item[0] => item[1]}
126
+ BrpmAuto.log "#=> Endpoint: #{servers.keys[0]}"
127
+ BrpmAuto.log "# Setting Properties:"
128
+ add_channel_properties(transfer_properties, servers, os)
129
+ brpd_compatibility(transfer_properties, nil, servers)
130
+ transfer_properties.each{|k,v| BrpmAuto.log "\t#{k} => #{v}" }
131
+ shebang = read_shebang(os, content)
132
+ BrpmAuto.log "Shebang: #{shebang.inspect}"
133
+ wrapper_path = build_wrapper_script(os, shebang, transfer_properties, {"script_target" => File.basename(script_file)})
134
+ BrpmAuto.log "# Wrapper: #{wrapper_path}"
135
+ target_path = @nsh.nsh_path(transfer_properties["RPM_CHANNEL_ROOT"])
136
+ BrpmAuto.log "# Copying script to target: "
137
+ clean_line_breaks(os, script_file, content)
138
+ result = @nsh.ncp(server_dns_names(servers), script_file, target_path)
139
+ grouped_result << result
140
+ BrpmAuto.log result
141
+ BrpmAuto.log "# Executing script on target via wrapper:"
142
+ result = @nsh.script_exec(server_dns_names(servers), wrapper_path, target_path)
143
+ grouped_result << result
144
+ BrpmAuto.log result
145
+ end
146
+ end
147
+ grouped_result.join("\n")
148
+ end
149
+
150
+ # Copies remote files to a local staging repository
151
+ #
152
+ # ==== Attributes
153
+ #
154
+ # * +file_list+ - array of nsh_paths
155
+ # * +options+ - hash of options, includes: version
156
+ # ==== Returns
157
+ #
158
+ # hash of instance_path and md5 - {"instance_path" => "", "md5" => ""}
159
+ #
160
+ def package_artifacts(file_list, options = {})
161
+ version = get_option(options, "version", "")
162
+ version = "#{get_param("SS_request_number")}_#{precision_timestamp}" if version == ""
163
+ staging_path = get_staging_dir(version, true)
164
+ BrpmAuto.message_box "Copying Files to Staging via NSH"
165
+ BrpmAuto.log "\t StagingPath: #{staging_path}"
166
+ file_list.each do |file_path|
167
+ BrpmAuto.log "\t #{file_path}"
168
+ result = @nsh.ncp(nil, @nsh.nsh_path(file_path), staging_path)
169
+ BrpmAuto.log "\tCopy Result: #{result}"
170
+ end
171
+ package_file = "package_#{version}.zip"
172
+ @nsh.package_staged_artifacts(staging_path, package_file)
173
+ end
174
+
175
+ # Deploys a packaged instance based on staging info
176
+ # staging info is generated by the stage_files routine
177
+ # ==== Attributes
178
+ #
179
+ # * +staging_info+ - hash returned by stage_files
180
+ # * +options+ - hash of options, includes allow_md5_mismatch(true/false) and target_path to override server channel_root
181
+ # ==== Returns
182
+ #
183
+ # action output
184
+ #
185
+ def deploy_package_instance(staging_info, options = {})
186
+ mismatch_ok = get_option(options, "allow_md5_mismatch", false)
187
+ target_path = get_option(options, "target_path")
188
+ seed_servers = get_option(options, "servers")
189
+ instance_path = staging_info["instance_path"]
190
+ BrpmAuto.message_box "Deploying Files to Targets via NSH"
191
+ return_result = {"payload_path" => "", "results" => "FAILURE"}
192
+ raise "Command_Failed: no artifacts staged in #{File.dirname(instance_path)}" if Dir.entries(File.dirname(instance_path)).size < 3
193
+ BrpmAuto.log "\t StagingArchive: #{instance_path}"
194
+ md5 = Digest::MD5.file(instance_path).hexdigest
195
+ md5_match = md5 == staging_info["md5"]
196
+ BrpmAuto.log "\t Checksum: expected: #{staging_info["md5"]} - actual: #{md5}#{md5_match ? " MATCHED" : " NO MATCH"}"
197
+ raise "Command_Failed: bad md5 checksum match" if !md5_match && !allow_md5_mismatch
198
+ result = "No servers to execute on"
199
+ # Loop through the platforms
200
+ OS_PLATFORMS.each do |os, os_details|
201
+ servers = BrpmAuto.params.get_servers_by_os_platform(os) if seed_servers == ""
202
+ servers = BrpmAuto.params.get_servers_by_os_platform(os, seed_servers) if seed_servers != ""
203
+ BrpmAuto.message_box "OS Platform: #{os_details["name"]}"
204
+ BrpmAuto.log "No servers selected for: #{os_details["name"]}" if servers.size == 0
205
+ next if servers.size == 0
206
+ BrpmAuto.log "# #{os_details["name"]} - Targets: #{servers.inspect}"
207
+ target_path = @nsh.nsh_path(target_path) if target_path != ""
208
+ target_path = @nsh.nsh_path(servers.first[1].has_key?("CHANNEL_ROOT") ? servers.first[1]["CHANNEL_ROOT"] : os_details["tmp_dir"]) if target_path == ""
209
+ final_path = File.join(target_path, get_param("SS_run_key"))
210
+ return_result["payload_path"] = File.join(final_path)
211
+ result = @nsh.script_execute_body(server_dns_names(servers), "mkdir #{final_path}", target_path)
212
+ BrpmAuto.log result
213
+ BrpmAuto.log "# Deploying package on target:"
214
+ result = @nsh.ncp(server_dns_names(servers), instance_path, final_path)
215
+ BrpmAuto.log result
216
+ BrpmAuto.log "# Unzipping package on target:"
217
+ wrapper_path = create_command_wrapper("unzip -o", os, instance_path, final_path)
218
+ result = @nsh.script_exec(server_dns_names(servers), wrapper_path, final_path)
219
+ BrpmAuto.log result
220
+ end
221
+ result
222
+ end
223
+
224
+ # Copies remote files to a local staging repository
225
+ #
226
+ # ==== Attributes
227
+ #
228
+ # * +source+ - nsh path to source file
229
+ # * +destination+ - path to destination file
230
+ # * +options+ - hash of options
231
+ #
232
+ def copy_file(source, destination, options = {})
233
+ BrpmAuto.message_box "Copying files via NSH"
234
+ BrpmAuto.log "\t Source: #{source}"
235
+ BrpmAuto.log "\t Destination: #{destination}"
236
+ result = @nsh.cp(source, destination)
237
+ BrpmAuto.log "\tCopy Result: #{result}"
238
+ result
239
+ end
240
+
241
+ end
242
+
243
+ @rpm.log "Initializing nsh transport"
244
+ baa_path = defined?(BAA_BASE_PATH) ? BAA_BASE_PATH : "/opt/bmc/bladelogic"
245
+ nsh_path = "#{BAA_BASE_PATH}/NSH"
246
+ @nsh = TransportNSH.new(nsh_path)
247
+ @rpm.log "Path to nsh: #{nsh_path}"
248
+ @transport = DispatchNSH.new(@nsh)