right_agent 2.0.7-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +82 -0
  3. data/Rakefile +113 -0
  4. data/lib/right_agent.rb +59 -0
  5. data/lib/right_agent/actor.rb +182 -0
  6. data/lib/right_agent/actor_registry.rb +76 -0
  7. data/lib/right_agent/actors/agent_manager.rb +232 -0
  8. data/lib/right_agent/agent.rb +1149 -0
  9. data/lib/right_agent/agent_config.rb +480 -0
  10. data/lib/right_agent/agent_identity.rb +210 -0
  11. data/lib/right_agent/agent_tag_manager.rb +237 -0
  12. data/lib/right_agent/audit_formatter.rb +107 -0
  13. data/lib/right_agent/clients.rb +31 -0
  14. data/lib/right_agent/clients/api_client.rb +383 -0
  15. data/lib/right_agent/clients/auth_client.rb +247 -0
  16. data/lib/right_agent/clients/balanced_http_client.rb +369 -0
  17. data/lib/right_agent/clients/base_retry_client.rb +495 -0
  18. data/lib/right_agent/clients/right_http_client.rb +279 -0
  19. data/lib/right_agent/clients/router_client.rb +493 -0
  20. data/lib/right_agent/command.rb +30 -0
  21. data/lib/right_agent/command/agent_manager_commands.rb +150 -0
  22. data/lib/right_agent/command/command_client.rb +136 -0
  23. data/lib/right_agent/command/command_constants.rb +33 -0
  24. data/lib/right_agent/command/command_io.rb +126 -0
  25. data/lib/right_agent/command/command_parser.rb +87 -0
  26. data/lib/right_agent/command/command_runner.rb +118 -0
  27. data/lib/right_agent/command/command_serializer.rb +63 -0
  28. data/lib/right_agent/connectivity_checker.rb +179 -0
  29. data/lib/right_agent/console.rb +65 -0
  30. data/lib/right_agent/core_payload_types.rb +44 -0
  31. data/lib/right_agent/core_payload_types/cookbook.rb +61 -0
  32. data/lib/right_agent/core_payload_types/cookbook_position.rb +46 -0
  33. data/lib/right_agent/core_payload_types/cookbook_repository.rb +116 -0
  34. data/lib/right_agent/core_payload_types/cookbook_sequence.rb +70 -0
  35. data/lib/right_agent/core_payload_types/dev_repositories.rb +100 -0
  36. data/lib/right_agent/core_payload_types/dev_repository.rb +76 -0
  37. data/lib/right_agent/core_payload_types/event_categories.rb +38 -0
  38. data/lib/right_agent/core_payload_types/executable_bundle.rb +130 -0
  39. data/lib/right_agent/core_payload_types/login_policy.rb +72 -0
  40. data/lib/right_agent/core_payload_types/login_user.rb +79 -0
  41. data/lib/right_agent/core_payload_types/planned_volume.rb +94 -0
  42. data/lib/right_agent/core_payload_types/recipe_instantiation.rb +73 -0
  43. data/lib/right_agent/core_payload_types/repositories_bundle.rb +50 -0
  44. data/lib/right_agent/core_payload_types/right_script_attachment.rb +95 -0
  45. data/lib/right_agent/core_payload_types/right_script_instantiation.rb +94 -0
  46. data/lib/right_agent/core_payload_types/runlist_policy.rb +44 -0
  47. data/lib/right_agent/core_payload_types/secure_document.rb +66 -0
  48. data/lib/right_agent/core_payload_types/secure_document_location.rb +63 -0
  49. data/lib/right_agent/core_payload_types/software_repository_instantiation.rb +61 -0
  50. data/lib/right_agent/daemonize.rb +35 -0
  51. data/lib/right_agent/dispatched_cache.rb +109 -0
  52. data/lib/right_agent/dispatcher.rb +272 -0
  53. data/lib/right_agent/enrollment_result.rb +221 -0
  54. data/lib/right_agent/exceptions.rb +87 -0
  55. data/lib/right_agent/history.rb +145 -0
  56. data/lib/right_agent/log.rb +460 -0
  57. data/lib/right_agent/minimal.rb +46 -0
  58. data/lib/right_agent/monkey_patches.rb +30 -0
  59. data/lib/right_agent/monkey_patches/ruby_patch.rb +55 -0
  60. data/lib/right_agent/monkey_patches/ruby_patch/array_patch.rb +29 -0
  61. data/lib/right_agent/monkey_patches/ruby_patch/darwin_patch.rb +24 -0
  62. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch.rb +24 -0
  63. data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +30 -0
  64. data/lib/right_agent/monkey_patches/ruby_patch/object_patch.rb +49 -0
  65. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch.rb +32 -0
  66. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +60 -0
  67. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/process_patch.rb +63 -0
  68. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/stdio_patch.rb +27 -0
  69. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/time_patch.rb +55 -0
  70. data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/win32ole_patch.rb +34 -0
  71. data/lib/right_agent/multiplexer.rb +102 -0
  72. data/lib/right_agent/offline_handler.rb +270 -0
  73. data/lib/right_agent/operation_result.rb +300 -0
  74. data/lib/right_agent/packets.rb +673 -0
  75. data/lib/right_agent/payload_formatter.rb +104 -0
  76. data/lib/right_agent/pending_requests.rb +128 -0
  77. data/lib/right_agent/pid_file.rb +159 -0
  78. data/lib/right_agent/platform.rb +770 -0
  79. data/lib/right_agent/platform/unix/darwin/platform.rb +102 -0
  80. data/lib/right_agent/platform/unix/linux/platform.rb +305 -0
  81. data/lib/right_agent/platform/unix/platform.rb +226 -0
  82. data/lib/right_agent/platform/windows/mingw/platform.rb +447 -0
  83. data/lib/right_agent/platform/windows/mswin/platform.rb +236 -0
  84. data/lib/right_agent/platform/windows/platform.rb +1808 -0
  85. data/lib/right_agent/protocol_version_mixin.rb +69 -0
  86. data/lib/right_agent/retryable_request.rb +195 -0
  87. data/lib/right_agent/scripts/agent_controller.rb +543 -0
  88. data/lib/right_agent/scripts/agent_deployer.rb +400 -0
  89. data/lib/right_agent/scripts/common_parser.rb +160 -0
  90. data/lib/right_agent/scripts/log_level_manager.rb +192 -0
  91. data/lib/right_agent/scripts/stats_manager.rb +268 -0
  92. data/lib/right_agent/scripts/usage.rb +58 -0
  93. data/lib/right_agent/secure_identity.rb +92 -0
  94. data/lib/right_agent/security.rb +32 -0
  95. data/lib/right_agent/security/cached_certificate_store_proxy.rb +77 -0
  96. data/lib/right_agent/security/certificate.rb +102 -0
  97. data/lib/right_agent/security/certificate_cache.rb +89 -0
  98. data/lib/right_agent/security/distinguished_name.rb +56 -0
  99. data/lib/right_agent/security/encrypted_document.rb +83 -0
  100. data/lib/right_agent/security/rsa_key_pair.rb +76 -0
  101. data/lib/right_agent/security/signature.rb +86 -0
  102. data/lib/right_agent/security/static_certificate_store.rb +85 -0
  103. data/lib/right_agent/sender.rb +792 -0
  104. data/lib/right_agent/serialize.rb +29 -0
  105. data/lib/right_agent/serialize/message_pack.rb +107 -0
  106. data/lib/right_agent/serialize/secure_serializer.rb +151 -0
  107. data/lib/right_agent/serialize/secure_serializer_initializer.rb +47 -0
  108. data/lib/right_agent/serialize/serializable.rb +151 -0
  109. data/lib/right_agent/serialize/serializer.rb +159 -0
  110. data/lib/right_agent/subprocess.rb +38 -0
  111. data/lib/right_agent/tracer.rb +124 -0
  112. data/right_agent.gemspec +101 -0
  113. data/spec/actor_registry_spec.rb +80 -0
  114. data/spec/actor_spec.rb +162 -0
  115. data/spec/agent_config_spec.rb +235 -0
  116. data/spec/agent_identity_spec.rb +78 -0
  117. data/spec/agent_spec.rb +734 -0
  118. data/spec/agent_tag_manager_spec.rb +319 -0
  119. data/spec/clients/api_client_spec.rb +423 -0
  120. data/spec/clients/auth_client_spec.rb +272 -0
  121. data/spec/clients/balanced_http_client_spec.rb +576 -0
  122. data/spec/clients/base_retry_client_spec.rb +635 -0
  123. data/spec/clients/router_client_spec.rb +594 -0
  124. data/spec/clients/spec_helper.rb +111 -0
  125. data/spec/command/agent_manager_commands_spec.rb +51 -0
  126. data/spec/command/command_io_spec.rb +93 -0
  127. data/spec/command/command_parser_spec.rb +79 -0
  128. data/spec/command/command_runner_spec.rb +107 -0
  129. data/spec/command/command_serializer_spec.rb +51 -0
  130. data/spec/connectivity_checker_spec.rb +83 -0
  131. data/spec/core_payload_types/dev_repositories_spec.rb +64 -0
  132. data/spec/core_payload_types/dev_repository_spec.rb +33 -0
  133. data/spec/core_payload_types/executable_bundle_spec.rb +67 -0
  134. data/spec/core_payload_types/login_user_spec.rb +102 -0
  135. data/spec/core_payload_types/recipe_instantiation_spec.rb +81 -0
  136. data/spec/core_payload_types/right_script_attachment_spec.rb +65 -0
  137. data/spec/core_payload_types/right_script_instantiation_spec.rb +79 -0
  138. data/spec/core_payload_types/spec_helper.rb +23 -0
  139. data/spec/dispatched_cache_spec.rb +136 -0
  140. data/spec/dispatcher_spec.rb +324 -0
  141. data/spec/enrollment_result_spec.rb +53 -0
  142. data/spec/history_spec.rb +246 -0
  143. data/spec/log_spec.rb +192 -0
  144. data/spec/monkey_patches/eventmachine_spec.rb +62 -0
  145. data/spec/multiplexer_spec.rb +48 -0
  146. data/spec/offline_handler_spec.rb +340 -0
  147. data/spec/operation_result_spec.rb +208 -0
  148. data/spec/packets_spec.rb +461 -0
  149. data/spec/pending_requests_spec.rb +136 -0
  150. data/spec/platform/spec_helper.rb +216 -0
  151. data/spec/platform/unix/darwin/platform_spec.rb +181 -0
  152. data/spec/platform/unix/linux/platform_spec.rb +540 -0
  153. data/spec/platform/unix/spec_helper.rb +149 -0
  154. data/spec/platform/windows/mingw/platform_spec.rb +222 -0
  155. data/spec/platform/windows/mswin/platform_spec.rb +259 -0
  156. data/spec/platform/windows/spec_helper.rb +720 -0
  157. data/spec/retryable_request_spec.rb +306 -0
  158. data/spec/secure_identity_spec.rb +50 -0
  159. data/spec/security/cached_certificate_store_proxy_spec.rb +62 -0
  160. data/spec/security/certificate_cache_spec.rb +71 -0
  161. data/spec/security/certificate_spec.rb +49 -0
  162. data/spec/security/distinguished_name_spec.rb +46 -0
  163. data/spec/security/encrypted_document_spec.rb +55 -0
  164. data/spec/security/rsa_key_pair_spec.rb +55 -0
  165. data/spec/security/signature_spec.rb +66 -0
  166. data/spec/security/static_certificate_store_spec.rb +58 -0
  167. data/spec/sender_spec.rb +1045 -0
  168. data/spec/serialize/message_pack_spec.rb +131 -0
  169. data/spec/serialize/secure_serializer_spec.rb +132 -0
  170. data/spec/serialize/serializable_spec.rb +90 -0
  171. data/spec/serialize/serializer_spec.rb +197 -0
  172. data/spec/spec.opts +2 -0
  173. data/spec/spec.win32.opts +1 -0
  174. data/spec/spec_helper.rb +130 -0
  175. data/spec/tracer_spec.rb +114 -0
  176. metadata +447 -0
@@ -0,0 +1,102 @@
1
+ #
2
+ # Copyright (c) 2009-2013 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require ::File.expand_path('../../platform', __FILE__)
24
+
25
+ module RightScale
26
+
27
+ # Mac OS specific implementation
28
+ class Platform
29
+
30
+ # Provides utilities for managing volumes (disks).
31
+ class VolumeManager
32
+
33
+ # Overrides base VolumeManager#volumes
34
+ def volumes(conditions = nil)
35
+ raise ::NotImplementedError, 'Not yet supporting Mac OS volume query'
36
+ end
37
+
38
+ # Overrides base VolumeManager#mount_volume
39
+ def mount_volume(volume, mountpoint)
40
+ raise ::NotImplementedError, 'Not yet supporting Mac OS volume mounting'
41
+ end
42
+ end
43
+
44
+ class Shell
45
+
46
+ # Overrides base Shell#uptime
47
+ def uptime
48
+ return (Time.now.to_i.to_f - booted_at.to_f) rescue 0.0
49
+ end
50
+
51
+ # Overrides base Shell#booted_at
52
+ def booted_at
53
+ output_text = execute('sysctl kern.boottime')
54
+ match = /sec = ([0-9]+)/.match(output_text)
55
+ if match && (match[1].to_i > 0)
56
+ return match[1].to_i
57
+ else
58
+ return nil
59
+ end
60
+ end
61
+ end # Shell
62
+
63
+ class Controller
64
+
65
+ # Overrides base Controller#reboot
66
+ def reboot
67
+ execute('shutdown -r now 2>&1')
68
+ true
69
+ end
70
+
71
+ # Overrides base Controller#shutdown
72
+ def shutdown
73
+ execute('shutdown -h now 2>&1')
74
+ true
75
+ end
76
+ end # Controller
77
+
78
+ class Installer
79
+
80
+ # Overrides base Installer#install
81
+ def install(packages)
82
+ raise ::NotImplementedError, 'Not yet supporting Mac OS package install'
83
+ end
84
+ end # Installer
85
+
86
+ private
87
+
88
+ # Overrides base Platform#initialize_species
89
+ def initialize_species
90
+ @flavor = 'mac_os_x'
91
+ begin
92
+ @release = execute('sw_vers -productVersion 2>&1').strip
93
+ @codename = '' # TEAL FIX cannot find a way to query osx codename by CLI
94
+ rescue ::RightScale::Platform::CommandError
95
+ @release = @codename = 'unknown'
96
+ end
97
+ true
98
+ end
99
+
100
+ end # Platform
101
+
102
+ end # RightScale
@@ -0,0 +1,305 @@
1
+ #
2
+ # Copyright (c) 2009-2013 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require ::File.expand_path('../../platform', __FILE__)
24
+
25
+ module RightScale
26
+
27
+ # Linux specific implementation
28
+ class Platform
29
+
30
+ FEDORA_REL = '/etc/fedora-release'
31
+ FEDORA_SIG = /Fedora release ([0-9]+) \((.*)\)/
32
+
33
+ # Is this machine running Ubuntu?
34
+ #
35
+ # @return [TrueClass|FalseClass] true if Linux flavor is Ubuntu
36
+ def ubuntu?
37
+ !!(@flavor =~ /ubuntu/)
38
+ end
39
+
40
+ # Is this machine running CentOS?
41
+ #
42
+ # @return [TrueClass|FalseClass] true if Linux flavor is CentOS
43
+ def centos?
44
+ !!(@flavor =~ /centos/)
45
+ end
46
+
47
+ # Is this machine running Suse?
48
+ #
49
+ # @return [TrueClass|FalseClass] true if Linux flavor is Suse
50
+ def suse?
51
+ !!(@flavor =~ /suse/)
52
+ end
53
+
54
+ # Is this machine running RHEL?
55
+ #
56
+ # @return [TrueClass|FalseClass] true if Linux flavor is RHEL
57
+ def rhel?
58
+ !!(@flavor =~ /redhatenterpriseserver/)
59
+ end
60
+
61
+ # Provides utilities for managing volumes (disks).
62
+ class VolumeManager
63
+
64
+ # Overrides base VolumeManager#volumes
65
+ def volumes(conditions = nil)
66
+ blkid_resp = execute('blkid 2>&1')
67
+ return parse_volumes(blkid_resp, conditions)
68
+ rescue ::RightScale::Platform::CommandError => e
69
+ raise VolumeError, "Failed to list volumes: #{e.message}"
70
+ end
71
+
72
+ # Overrides base VolumeManager#mount_volume
73
+ def mount_volume(volume, mountpoint)
74
+ unless volume.is_a?(::Hash) && volume[:device]
75
+ raise ::ArgumentError, "Invalid volume argument = #{volume.inspect}"
76
+ end
77
+ mount_list_output = nil
78
+ begin
79
+ mount_list_output = execute('mount 2>&1')
80
+ rescue ::RightScale::Platform::CommandError => e
81
+ raise VolumeError, "Failed interrogation of current mounts: #{e.message}"
82
+ end
83
+
84
+ device_match = /^#{volume[:device]} on (.+?)\s/.match(mount_list_output)
85
+ mountpoint_from_device_match = device_match ? device_match[1] : mountpoint
86
+ unless (mountpoint_from_device_match && mountpoint_from_device_match == mountpoint)
87
+ raise VolumeError,
88
+ "Attempted to mount volume \"#{volume[:device]}\" at \"#{mountpoint}\" but it was already mounted at #{mountpoint_from_device_match}"
89
+ end
90
+
91
+ mountpoint_match = /^(.+?) on #{mountpoint}/.match(mount_list_output)
92
+ device_from_mountpoint_match = mountpoint_match ? mountpoint_match[1] : volume[:device]
93
+ unless (device_from_mountpoint_match && device_from_mountpoint_match == volume[:device])
94
+ raise VolumeError.new("Attempted to mount volume \"#{volume[:device]}\" at \"#{mountpoint}\" but \"#{device_from_mountpoint_match}\" was already mounted there.")
95
+ end
96
+
97
+ # The volume is already mounted at the correct mountpoint
98
+ return true if /^#{volume[:device]} on #{mountpoint}/.match(mount_list_output)
99
+
100
+ # TODO: Maybe validate that the mountpoint is valid *nix path?
101
+ begin
102
+ execute("mount -t #{volume[:filesystem].strip} #{volume[:device]} #{mountpoint} 2>&1")
103
+ rescue ::RightScale::Platform::CommandError => e
104
+ raise VolumeError, "Failed to mount volume to \"#{mountpoint}\" with device \"#{volume[:device]}\": #{e.message}"
105
+ end
106
+ true
107
+ end
108
+
109
+ private
110
+
111
+ # Parses raw output from `blkid` into a hash of volumes.
112
+ #
113
+ # The hash will contain the device name with a key of :device, and each
114
+ # key value pair for the device. In order to keep parity with the Windows
115
+ # VolumeManager.parse_volumes method, the :type key will be duplicated as
116
+ # :filesystem
117
+ #
118
+ # Example of raw output from `blkid`
119
+ # /dev/xvdh1: SEC_TYPE="msdos" LABEL="METADATA" UUID="681B-8C5D" TYPE="vfat"
120
+ # /dev/xvdb1: LABEL="SWAP-xvdb1" UUID="d51fcca0-6b10-4934-a572-f3898dfd8840" TYPE="swap"
121
+ # /dev/xvda1: UUID="f4746f9c-0557-4406-9267-5e918e87ca2e" TYPE="ext3"
122
+ # /dev/xvda2: UUID="14d88b9e-9fe6-4974-a8d6-180acdae4016" TYPE="ext3"
123
+ #
124
+ # @param [String] output_text from blkid
125
+ # @param [Hash] conditions to match (Default = no conditions)
126
+ #
127
+ # @return [Array] volume info as an array of hashes or empty
128
+ #
129
+ # @raise [ParserError] on failure to parse volume list
130
+ def parse_volumes(output_text, conditions = nil)
131
+ results = []
132
+ output_text.lines.each do |line|
133
+ volume = {}
134
+ line_regex = /^([\/a-z0-9_\-\.]+):(.*)/
135
+ volmatch = line_regex.match(line)
136
+ raise ParserError.new("Failed to parse volume info from #{line.inspect} using #{line_regex.inspect}") unless volmatch
137
+ volume[:device] = volmatch[1]
138
+ volmatch[2].split(' ').each do |pair|
139
+ pair_regex = /([a-zA-Z_\-]+)=(.*)/
140
+ match = pair_regex.match(pair)
141
+ raise ParserError.new("Failed to parse volume info from #{pair} using #{pair_regex.inspect}") unless match
142
+ volume[:"#{match[1].downcase}"] = match[2].gsub('"', '')
143
+ # Make this as much like the windows output as possible
144
+ if match[1] == 'TYPE'
145
+ volume[:filesystem] = match[2].gsub('"', '')
146
+ end
147
+ end
148
+ if conditions
149
+ matched = true
150
+ conditions.each do |key,value|
151
+ unless volume[key] == value
152
+ matched = false
153
+ break
154
+ end
155
+ end
156
+ results << volume if matched
157
+ else
158
+ results << volume
159
+ end
160
+ end
161
+ results
162
+ end
163
+ end # VolumeManager
164
+
165
+ class Shell
166
+
167
+ # Overrides base Shell#uptime
168
+ def uptime
169
+ return ::File.read('/proc/uptime').split(/\s+/)[0].to_f rescue 0.0
170
+ end
171
+
172
+ # Overrides base Shell#booted_at
173
+ def booted_at
174
+ match = /btime ([0-9]+)/.match(::File.read('/proc/stat')) rescue nil
175
+ if match && (match[1].to_i > 0)
176
+ return match[1].to_i
177
+ else
178
+ return nil
179
+ end
180
+ end
181
+ end # Shell
182
+
183
+ class Controller
184
+
185
+ # Overrides base Controller#reboot
186
+ def reboot
187
+ execute('init 6 2>&1')
188
+ true
189
+ end
190
+
191
+ # Overrides base Controller#shutdown
192
+ def shutdown
193
+ execute('init 0 2>&1')
194
+ true
195
+ end
196
+ end # Controller
197
+
198
+ class Installer
199
+
200
+ # Does this machine have aptitude?
201
+ #
202
+ # @return [TrueClass|FalseClass] true if aptitude is available in the expected directory
203
+ def aptitude?
204
+ ::File.executable? '/usr/bin/apt-get'
205
+ end
206
+
207
+ # Does this machine have yum?
208
+ #
209
+ # @return [TrueClass|FalseClass] true if yum is available in the expected directory
210
+ def yum?
211
+ ::File.executable? '/usr/bin/yum'
212
+ end
213
+
214
+ # Does this machine have zypper?
215
+ #
216
+ # @return [TrueClass|FalseClass] true if zypper is available in the expected directory
217
+ def zypper?
218
+ ::File.executable? '/usr/bin/zypper'
219
+ end
220
+
221
+ # Overrides base Installer#install
222
+ def install(packages)
223
+ packages = Array(packages)
224
+ return true if packages.empty?
225
+
226
+ packages = packages.uniq.join(' ')
227
+
228
+ if yum?
229
+ command = "yum install -y #{packages} 2>&1"
230
+ regex = /No package (.*) available\./
231
+ elsif aptitude?
232
+ old_debian_frontend = ENV['DEBIAN_FRONTEND']
233
+ ENV['DEBIAN_FRONTEND'] = 'noninteractive'
234
+ command = "apt-get install -y #{packages} 2>&1"
235
+ # note the error message for apt-get seems to have changed between
236
+ # versions of aptitude.
237
+ regex = /E: (Couldn't find package|Unable to locate package) (.*)/
238
+ elsif zypper?
239
+ command = "zypper --no-gpg-checks -n #{packages} 2>&1"
240
+ regex = /Package '(.*)' not found\./
241
+ else
242
+ raise PackageManagerNotFound,
243
+ 'No package manager binary (apt, yum, zypper) found in /usr/bin'
244
+ end
245
+
246
+ failed_packages = nil
247
+ begin
248
+ # TEAL FIX it's not clear from legacy implementation if having failed
249
+ # packages consistently exits non-zero from all supported installers.
250
+ # for that reason, also scan for failed packages on exit zero.
251
+ failed_packages = scan_for_failed_packages(execute(command), regex)
252
+ rescue ::RightScale::Platform::CommandError => e
253
+ # command could fail for reasons other than failed packages (e.g. not
254
+ # being sudo) but legacy code raised a specific error for failed
255
+ # packages.
256
+ failed_packages = scan_for_failed_packages(e.output_text, regex)
257
+ raise if failed_packages.empty?
258
+ ensure
259
+ ENV['DEBIAN_FRONTEND'] = old_debian_frontend if aptitude?
260
+ end
261
+ unless failed_packages.empty?
262
+ raise PackageNotFound,
263
+ "The following packages were not available: #{failed_packages.join(', ')}"
264
+ end
265
+ true
266
+ end
267
+
268
+ private
269
+
270
+ def scan_for_failed_packages(output_text, regex)
271
+ @output = output_text
272
+ failed_packages = []
273
+ output_text.scan(regex) { |package| failed_packages << package.last }
274
+ failed_packages
275
+ end
276
+ end # Installer
277
+
278
+ private
279
+
280
+ # Overrides base Platform#initialize_species
281
+ def initialize_species
282
+ # Use the lsb_release utility if it's available
283
+ begin
284
+ # TEAL FIX: not sure if we really need to check if --help succeeds or
285
+ # if we would only need to call lsb_release -is but that was the legacy
286
+ # behavior and retesting all supported flavors of Linux isn't trivial.
287
+ execute('lsb_release --help >/dev/null 2>&1')
288
+ @flavor = execute('lsb_release -is', :raise_on_failure => false).strip.downcase
289
+ @release = execute('lsb_release -rs', :raise_on_failure => false).strip
290
+ @codename = execute('lsb_release -cs', :raise_on_failure => false).strip
291
+ rescue ::RightScale::Platform::CommandError
292
+ if ::File.exist?(FEDORA_REL) && (match = FEDORA_SIG.match(::File.read(FEDORA_REL)))
293
+ # Parse the fedora-release file if it exists
294
+ @flavor = 'fedora'
295
+ @release = match[1]
296
+ @codename = match[2]
297
+ else
298
+ @flavor = @release = @codename = 'unknown'
299
+ end
300
+ end
301
+ true
302
+ end
303
+
304
+ end # Platform
305
+ end # RightScale
@@ -0,0 +1,226 @@
1
+ #
2
+ # Copyright (c) 2013 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require ::File.expand_path('../../../platform', __FILE__)
24
+
25
+ module RightScale
26
+
27
+ # Unix-specific implementation
28
+ class Platform
29
+
30
+ class Filesystem
31
+
32
+ # Overrides base Filesystem#find_executable_in_path
33
+ def find_executable_in_path(command_name)
34
+ ::ENV['PATH'].split(/;|:/).each do |dir|
35
+ path = ::File.join(dir, command_name)
36
+ return path if ::File.executable?(path)
37
+ end
38
+ return nil
39
+ end
40
+
41
+ # Overrides base Filesystem#right_agent_cfg_dir
42
+ def right_agent_cfg_dir
43
+ '/var/lib/rightscale/right_agent'
44
+ end
45
+
46
+ # Overrides base Filesystem#right_scale_static_state_dir
47
+ def right_scale_static_state_dir
48
+ '/etc/rightscale.d'
49
+ end
50
+
51
+ # Overrides base Filesystem#right_link_static_state_dir
52
+ def right_link_static_state_dir
53
+ '/etc/rightscale.d/right_link'
54
+ end
55
+
56
+ # Overrides base Filesystem#right_link_dynamic_state_dir
57
+ def right_link_dynamic_state_dir
58
+ '/var/lib/rightscale/right_link'
59
+ end
60
+
61
+ # Overrides base Filesystem#spool_dir
62
+ def spool_dir
63
+ '/var/spool'
64
+ end
65
+
66
+ # Overrides base Filesystem#ssh_cfg_dir
67
+ def ssh_cfg_dir
68
+ '/etc/ssh'
69
+ end
70
+
71
+ # Overrides base Filesystem#cache_dir
72
+ def cache_dir
73
+ '/var/cache'
74
+ end
75
+
76
+ # Overrides base Filesystem#log_dir
77
+ def log_dir
78
+ '/var/log'
79
+ end
80
+
81
+ # Overrides base Filesystem#source_code_dir
82
+ def source_code_dir
83
+ '/usr/src'
84
+ end
85
+
86
+ # Overrides base Filesystem#temp_dir
87
+ def temp_dir
88
+ '/tmp'
89
+ end
90
+
91
+ # Overrides base Filesystem#pid_dir
92
+ def pid_dir
93
+ '/var/run'
94
+ end
95
+
96
+ # Overrides base Filesystem#right_link_home_dir
97
+ def right_link_home_dir
98
+ # TEAL FIX could the user choose a different directory when installing
99
+ # the RightLink v5.9+ package manually?
100
+ '/opt/rightscale'
101
+ end
102
+
103
+ # Overrides base Filesystem#private_bin_dir
104
+ def private_bin_dir
105
+ ::File.join(right_link_home_dir, 'bin')
106
+ end
107
+
108
+ # Overrides base Filesystem#sandbox_dir
109
+ def sandbox_dir
110
+ ::File.join(right_link_home_dir, 'sandbox')
111
+ end
112
+
113
+ # Overrides base Filesystem#long_path_to_short_path
114
+ def long_path_to_short_path(long_path)
115
+ return long_path
116
+ end
117
+
118
+ # Overrides base Filesystem#pretty_path
119
+ def pretty_path(path, native_fs_flag = false)
120
+ return path
121
+ end
122
+
123
+ # Overrides base Filesystem#ensure_local_drive_path
124
+ def ensure_local_drive_path(path, temp_dir_name)
125
+ return path
126
+ end
127
+
128
+ # Overrides base Filesystem#create_symlink
129
+ def create_symlink(from_path, to_path)
130
+ ::File.symlink(from_path, to_path)
131
+ end
132
+ end
133
+
134
+ # Provides utilities for managing volumes (disks).
135
+ class VolumeManager
136
+
137
+ # Mounts a volume (returned by VolumeManager.volumes) to the mountpoint
138
+ # specified.
139
+ #
140
+ # @param [Hash] volume info hash (as returned by VolumeManager.volumes)
141
+ # @param [String] mountpoint where the device will be mounted in the file system
142
+ #
143
+ # @return [TrueClass] always true
144
+ #
145
+ # @raise [VolumeError] on a failure to mount the device
146
+ def mount_volume(volume, mountpoint)
147
+ must_be_overridden
148
+ end
149
+ end # VolumeManager
150
+
151
+ class Shell
152
+ # defined for backward compatibility; use Shell#null_output_name
153
+ NULL_OUTPUT_NAME = '/dev/null'
154
+
155
+ # Overrides base Shell#null_output_name
156
+ def null_output_name
157
+ NULL_OUTPUT_NAME
158
+ end
159
+
160
+ # Overrides base Shell#format_script_file_name
161
+ def format_script_file_name(partial_script_file_path, default_extension = nil)
162
+ # shell files containing shebang are directly executable in Unix, so
163
+ # assume our scripts have shebang. if not, the error should be obvious.
164
+ return partial_script_file_path
165
+ end
166
+
167
+ # Overrides base Shell#format_executable_command
168
+ def format_executable_command(executable_file_path, *arguments)
169
+ escaped = []
170
+ space = ' '
171
+ double_quote = '"'
172
+ single_quote = "'"
173
+ [executable_file_path, arguments].flatten.each do |arg|
174
+ value = arg.to_s
175
+ needs_escape =
176
+ value.index(space) ||
177
+ value.index(double_quote) ||
178
+ value.index(single_quote)
179
+ escaped << (needs_escape ? "\"#{value.gsub(double_quote, "\\\"")}\"" : value)
180
+ end
181
+ return escaped.join(space)
182
+ end
183
+
184
+ # Overrides base Shell#format_shell_command
185
+ def format_shell_command(shell_script_file_path, *arguments)
186
+ # shell files containing shebang are directly executable in Unix, so
187
+ # assume our scripts have shebang. if not, the error should be obvious.
188
+ return format_executable_command(shell_script_file_path, arguments)
189
+ end
190
+
191
+ # Overrides base Shell#sandbox_ruby
192
+ def sandbox_ruby
193
+ "#{::RightScale::Platform.filesystem.sandbox_dir}/bin/ruby"
194
+ end
195
+ end
196
+
197
+ class Rng
198
+
199
+ # Overrides base Rng#pseudorandom_bytes
200
+ def pseudorandom_bytes(count)
201
+ result = nil
202
+ ::File.open('/dev/urandom', 'r') { |f| result = f.read(count) }
203
+ result
204
+ end
205
+ end
206
+
207
+ class Process
208
+
209
+ # Overrides base Process#resident_set_size
210
+ def resident_set_size(pid = nil)
211
+ pid = $$ unless pid
212
+ output_text = execute("ps -o rss= -p #{pid}")
213
+ return output_text.to_i
214
+ end
215
+ end
216
+
217
+ private
218
+
219
+ # Overrides base Platform#initialize_genus
220
+ def initialize_genus
221
+ true # do nothing
222
+ end
223
+
224
+ end # Platform
225
+
226
+ end # RightScale