brpm_content_framework 0.1.55

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.
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)