right_agent 2.0.7-x86-mingw32

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 (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