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.
- data/LICENSE +20 -0
- data/README.rdoc +82 -0
- data/Rakefile +113 -0
- data/lib/right_agent.rb +59 -0
- data/lib/right_agent/actor.rb +182 -0
- data/lib/right_agent/actor_registry.rb +76 -0
- data/lib/right_agent/actors/agent_manager.rb +232 -0
- data/lib/right_agent/agent.rb +1149 -0
- data/lib/right_agent/agent_config.rb +480 -0
- data/lib/right_agent/agent_identity.rb +210 -0
- data/lib/right_agent/agent_tag_manager.rb +237 -0
- data/lib/right_agent/audit_formatter.rb +107 -0
- data/lib/right_agent/clients.rb +31 -0
- data/lib/right_agent/clients/api_client.rb +383 -0
- data/lib/right_agent/clients/auth_client.rb +247 -0
- data/lib/right_agent/clients/balanced_http_client.rb +369 -0
- data/lib/right_agent/clients/base_retry_client.rb +495 -0
- data/lib/right_agent/clients/right_http_client.rb +279 -0
- data/lib/right_agent/clients/router_client.rb +493 -0
- data/lib/right_agent/command.rb +30 -0
- data/lib/right_agent/command/agent_manager_commands.rb +150 -0
- data/lib/right_agent/command/command_client.rb +136 -0
- data/lib/right_agent/command/command_constants.rb +33 -0
- data/lib/right_agent/command/command_io.rb +126 -0
- data/lib/right_agent/command/command_parser.rb +87 -0
- data/lib/right_agent/command/command_runner.rb +118 -0
- data/lib/right_agent/command/command_serializer.rb +63 -0
- data/lib/right_agent/connectivity_checker.rb +179 -0
- data/lib/right_agent/console.rb +65 -0
- data/lib/right_agent/core_payload_types.rb +44 -0
- data/lib/right_agent/core_payload_types/cookbook.rb +61 -0
- data/lib/right_agent/core_payload_types/cookbook_position.rb +46 -0
- data/lib/right_agent/core_payload_types/cookbook_repository.rb +116 -0
- data/lib/right_agent/core_payload_types/cookbook_sequence.rb +70 -0
- data/lib/right_agent/core_payload_types/dev_repositories.rb +100 -0
- data/lib/right_agent/core_payload_types/dev_repository.rb +76 -0
- data/lib/right_agent/core_payload_types/event_categories.rb +38 -0
- data/lib/right_agent/core_payload_types/executable_bundle.rb +130 -0
- data/lib/right_agent/core_payload_types/login_policy.rb +72 -0
- data/lib/right_agent/core_payload_types/login_user.rb +79 -0
- data/lib/right_agent/core_payload_types/planned_volume.rb +94 -0
- data/lib/right_agent/core_payload_types/recipe_instantiation.rb +73 -0
- data/lib/right_agent/core_payload_types/repositories_bundle.rb +50 -0
- data/lib/right_agent/core_payload_types/right_script_attachment.rb +95 -0
- data/lib/right_agent/core_payload_types/right_script_instantiation.rb +94 -0
- data/lib/right_agent/core_payload_types/runlist_policy.rb +44 -0
- data/lib/right_agent/core_payload_types/secure_document.rb +66 -0
- data/lib/right_agent/core_payload_types/secure_document_location.rb +63 -0
- data/lib/right_agent/core_payload_types/software_repository_instantiation.rb +61 -0
- data/lib/right_agent/daemonize.rb +35 -0
- data/lib/right_agent/dispatched_cache.rb +109 -0
- data/lib/right_agent/dispatcher.rb +272 -0
- data/lib/right_agent/enrollment_result.rb +221 -0
- data/lib/right_agent/exceptions.rb +87 -0
- data/lib/right_agent/history.rb +145 -0
- data/lib/right_agent/log.rb +460 -0
- data/lib/right_agent/minimal.rb +46 -0
- data/lib/right_agent/monkey_patches.rb +30 -0
- data/lib/right_agent/monkey_patches/ruby_patch.rb +55 -0
- data/lib/right_agent/monkey_patches/ruby_patch/array_patch.rb +29 -0
- data/lib/right_agent/monkey_patches/ruby_patch/darwin_patch.rb +24 -0
- data/lib/right_agent/monkey_patches/ruby_patch/linux_patch.rb +24 -0
- data/lib/right_agent/monkey_patches/ruby_patch/linux_patch/file_patch.rb +30 -0
- data/lib/right_agent/monkey_patches/ruby_patch/object_patch.rb +49 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch.rb +32 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/file_patch.rb +60 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/process_patch.rb +63 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/stdio_patch.rb +27 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/time_patch.rb +55 -0
- data/lib/right_agent/monkey_patches/ruby_patch/windows_patch/win32ole_patch.rb +34 -0
- data/lib/right_agent/multiplexer.rb +102 -0
- data/lib/right_agent/offline_handler.rb +270 -0
- data/lib/right_agent/operation_result.rb +300 -0
- data/lib/right_agent/packets.rb +673 -0
- data/lib/right_agent/payload_formatter.rb +104 -0
- data/lib/right_agent/pending_requests.rb +128 -0
- data/lib/right_agent/pid_file.rb +159 -0
- data/lib/right_agent/platform.rb +770 -0
- data/lib/right_agent/platform/unix/darwin/platform.rb +102 -0
- data/lib/right_agent/platform/unix/linux/platform.rb +305 -0
- data/lib/right_agent/platform/unix/platform.rb +226 -0
- data/lib/right_agent/platform/windows/mingw/platform.rb +447 -0
- data/lib/right_agent/platform/windows/mswin/platform.rb +236 -0
- data/lib/right_agent/platform/windows/platform.rb +1808 -0
- data/lib/right_agent/protocol_version_mixin.rb +69 -0
- data/lib/right_agent/retryable_request.rb +195 -0
- data/lib/right_agent/scripts/agent_controller.rb +543 -0
- data/lib/right_agent/scripts/agent_deployer.rb +400 -0
- data/lib/right_agent/scripts/common_parser.rb +160 -0
- data/lib/right_agent/scripts/log_level_manager.rb +192 -0
- data/lib/right_agent/scripts/stats_manager.rb +268 -0
- data/lib/right_agent/scripts/usage.rb +58 -0
- data/lib/right_agent/secure_identity.rb +92 -0
- data/lib/right_agent/security.rb +32 -0
- data/lib/right_agent/security/cached_certificate_store_proxy.rb +77 -0
- data/lib/right_agent/security/certificate.rb +102 -0
- data/lib/right_agent/security/certificate_cache.rb +89 -0
- data/lib/right_agent/security/distinguished_name.rb +56 -0
- data/lib/right_agent/security/encrypted_document.rb +83 -0
- data/lib/right_agent/security/rsa_key_pair.rb +76 -0
- data/lib/right_agent/security/signature.rb +86 -0
- data/lib/right_agent/security/static_certificate_store.rb +85 -0
- data/lib/right_agent/sender.rb +792 -0
- data/lib/right_agent/serialize.rb +29 -0
- data/lib/right_agent/serialize/message_pack.rb +107 -0
- data/lib/right_agent/serialize/secure_serializer.rb +151 -0
- data/lib/right_agent/serialize/secure_serializer_initializer.rb +47 -0
- data/lib/right_agent/serialize/serializable.rb +151 -0
- data/lib/right_agent/serialize/serializer.rb +159 -0
- data/lib/right_agent/subprocess.rb +38 -0
- data/lib/right_agent/tracer.rb +124 -0
- data/right_agent.gemspec +101 -0
- data/spec/actor_registry_spec.rb +80 -0
- data/spec/actor_spec.rb +162 -0
- data/spec/agent_config_spec.rb +235 -0
- data/spec/agent_identity_spec.rb +78 -0
- data/spec/agent_spec.rb +734 -0
- data/spec/agent_tag_manager_spec.rb +319 -0
- data/spec/clients/api_client_spec.rb +423 -0
- data/spec/clients/auth_client_spec.rb +272 -0
- data/spec/clients/balanced_http_client_spec.rb +576 -0
- data/spec/clients/base_retry_client_spec.rb +635 -0
- data/spec/clients/router_client_spec.rb +594 -0
- data/spec/clients/spec_helper.rb +111 -0
- data/spec/command/agent_manager_commands_spec.rb +51 -0
- data/spec/command/command_io_spec.rb +93 -0
- data/spec/command/command_parser_spec.rb +79 -0
- data/spec/command/command_runner_spec.rb +107 -0
- data/spec/command/command_serializer_spec.rb +51 -0
- data/spec/connectivity_checker_spec.rb +83 -0
- data/spec/core_payload_types/dev_repositories_spec.rb +64 -0
- data/spec/core_payload_types/dev_repository_spec.rb +33 -0
- data/spec/core_payload_types/executable_bundle_spec.rb +67 -0
- data/spec/core_payload_types/login_user_spec.rb +102 -0
- data/spec/core_payload_types/recipe_instantiation_spec.rb +81 -0
- data/spec/core_payload_types/right_script_attachment_spec.rb +65 -0
- data/spec/core_payload_types/right_script_instantiation_spec.rb +79 -0
- data/spec/core_payload_types/spec_helper.rb +23 -0
- data/spec/dispatched_cache_spec.rb +136 -0
- data/spec/dispatcher_spec.rb +324 -0
- data/spec/enrollment_result_spec.rb +53 -0
- data/spec/history_spec.rb +246 -0
- data/spec/log_spec.rb +192 -0
- data/spec/monkey_patches/eventmachine_spec.rb +62 -0
- data/spec/multiplexer_spec.rb +48 -0
- data/spec/offline_handler_spec.rb +340 -0
- data/spec/operation_result_spec.rb +208 -0
- data/spec/packets_spec.rb +461 -0
- data/spec/pending_requests_spec.rb +136 -0
- data/spec/platform/spec_helper.rb +216 -0
- data/spec/platform/unix/darwin/platform_spec.rb +181 -0
- data/spec/platform/unix/linux/platform_spec.rb +540 -0
- data/spec/platform/unix/spec_helper.rb +149 -0
- data/spec/platform/windows/mingw/platform_spec.rb +222 -0
- data/spec/platform/windows/mswin/platform_spec.rb +259 -0
- data/spec/platform/windows/spec_helper.rb +720 -0
- data/spec/retryable_request_spec.rb +306 -0
- data/spec/secure_identity_spec.rb +50 -0
- data/spec/security/cached_certificate_store_proxy_spec.rb +62 -0
- data/spec/security/certificate_cache_spec.rb +71 -0
- data/spec/security/certificate_spec.rb +49 -0
- data/spec/security/distinguished_name_spec.rb +46 -0
- data/spec/security/encrypted_document_spec.rb +55 -0
- data/spec/security/rsa_key_pair_spec.rb +55 -0
- data/spec/security/signature_spec.rb +66 -0
- data/spec/security/static_certificate_store_spec.rb +58 -0
- data/spec/sender_spec.rb +1045 -0
- data/spec/serialize/message_pack_spec.rb +131 -0
- data/spec/serialize/secure_serializer_spec.rb +132 -0
- data/spec/serialize/serializable_spec.rb +90 -0
- data/spec/serialize/serializer_spec.rb +197 -0
- data/spec/spec.opts +2 -0
- data/spec/spec.win32.opts +1 -0
- data/spec/spec_helper.rb +130 -0
- data/spec/tracer_spec.rb +114 -0
- metadata +447 -0
@@ -0,0 +1,720 @@
|
|
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('../../spec_helper', __FILE__)
|
24
|
+
|
25
|
+
shared_examples_for 'supports windows platform statics' do
|
26
|
+
it 'should be Windows' do
|
27
|
+
subject.unix?.should be_false
|
28
|
+
subject.windows?.should be_true
|
29
|
+
subject.linux?.should be_false
|
30
|
+
subject.darwin?.should be_false
|
31
|
+
end
|
32
|
+
end # supports windows platform statics
|
33
|
+
|
34
|
+
shared_examples_for 'supports windows platform initialization' do
|
35
|
+
it 'should query os info during initialize' do
|
36
|
+
instrument_os_info(6, 1, 7601)
|
37
|
+
platform_instance.send(:initialize_genus)
|
38
|
+
platform_instance.release.should == '6.1.7601'
|
39
|
+
platform_instance.codename.should == ''
|
40
|
+
end
|
41
|
+
end # supports windows platform initialization
|
42
|
+
|
43
|
+
shared_examples_for 'supports windows platform filesystem' do
|
44
|
+
context '#find_executable_in_path' do
|
45
|
+
let(:pathexts) { %w[.EXE .BAT] }
|
46
|
+
let(:paths) { %w[C:\Windows\system32 C:\Windows C:\Windows\System32\Wbem] }
|
47
|
+
let(:pathext_env) { pathexts.join(';') }
|
48
|
+
let(:path_env) { paths.join(';') }
|
49
|
+
let(:expected_path) { 'C:/Windows/foo.EXE' }
|
50
|
+
|
51
|
+
it 'should find executable' do
|
52
|
+
mock_env = flexmock(::ENV)
|
53
|
+
mock_env.should_receive(:[]).with('PATHEXT').and_return(pathext_env)
|
54
|
+
mock_env.should_receive(:[]).with('PATH').and_return(path_env)
|
55
|
+
|
56
|
+
all_paths = [::Dir.getwd.gsub("\\", '/')] + paths
|
57
|
+
foo_found = false
|
58
|
+
all_paths.each do |path|
|
59
|
+
pathexts.each do |pathext|
|
60
|
+
unless foo_found
|
61
|
+
foo_path = ::File.join(path.gsub("\\", '/'), 'foo' + pathext)
|
62
|
+
foo_matched = foo_path == expected_path
|
63
|
+
file_class.should_receive(:executable?).
|
64
|
+
with(foo_path).
|
65
|
+
and_return(foo_matched).
|
66
|
+
twice
|
67
|
+
foo_found = foo_matched
|
68
|
+
end
|
69
|
+
bar_path = ::File.join(path.gsub("\\", '/'), 'bar' + pathext)
|
70
|
+
file_class.should_receive(:executable?).with(bar_path).and_return(false).twice
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
subject.find_executable_in_path('foo').should == expected_path
|
75
|
+
subject.has_executable_in_path('foo').should be_true
|
76
|
+
subject.find_executable_in_path('bar').should be_nil
|
77
|
+
subject.has_executable_in_path('bar').should be_false
|
78
|
+
end
|
79
|
+
end # find_executable_in_path
|
80
|
+
|
81
|
+
context 'paths' do
|
82
|
+
context 'constants' do
|
83
|
+
before(:each) do
|
84
|
+
# win32/dir-based constants.
|
85
|
+
subject.should_receive(:common_app_data_dir).and_return('C:/ProgramData')
|
86
|
+
subject.should_receive(:program_files_dir).and_return('C:/Program Files (x86)')
|
87
|
+
|
88
|
+
# ENV-based constants.
|
89
|
+
@mock_env = flexmock(::ENV)
|
90
|
+
@mock_env.should_receive(:[]).with('SystemRoot').and_return("C:\\Windows")
|
91
|
+
@mock_env.should_receive(:[]).with('USERPROFILE').and_return("C:\\Users\\foo")
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should return windows path constants' do
|
95
|
+
# windows-specific constants.
|
96
|
+
subject.company_app_data_dir.should == 'C:/ProgramData/RightScale'
|
97
|
+
subject.company_program_files_dir.should == 'C:/Program Files (x86)/RightScale'
|
98
|
+
subject.system_root.should == 'C:/Windows'
|
99
|
+
subject.user_home_dir.should == 'C:/Users/foo'
|
100
|
+
|
101
|
+
# constants available to all platforms.
|
102
|
+
subject.right_agent_cfg_dir.should == 'C:/ProgramData/RightScale/right_agent'
|
103
|
+
subject.right_scale_static_state_dir.should == 'C:/ProgramData/RightScale/rightscale.d'
|
104
|
+
subject.right_link_static_state_dir.should == 'C:/ProgramData/RightScale/rightscale.d/right_link'
|
105
|
+
subject.right_link_dynamic_state_dir.should == 'C:/ProgramData/RightScale/right_link'
|
106
|
+
subject.spool_dir.should == 'C:/ProgramData/RightScale/spool'
|
107
|
+
subject.ssh_cfg_dir.should == 'C:/Users/foo/.ssh'
|
108
|
+
subject.cache_dir.should == 'C:/ProgramData/RightScale/cache'
|
109
|
+
subject.log_dir.should == 'C:/ProgramData/RightScale/log'
|
110
|
+
subject.source_code_dir.should == 'C:/ProgramData/RightScale/src'
|
111
|
+
subject.pid_dir.should == 'C:/ProgramData/RightScale/run'
|
112
|
+
|
113
|
+
@mock_env.
|
114
|
+
should_receive(:[]).
|
115
|
+
with('RS_RIGHT_LINK_HOME').
|
116
|
+
and_return("C:\\PROGRA~2\\RIGHTS~1\\RIGHTL~1")
|
117
|
+
file_class.
|
118
|
+
should_receive(:normalize_path).
|
119
|
+
with('C:/PROGRA~2/RIGHTS~1/RIGHTL~1').
|
120
|
+
and_return('C:/PROGRA~2/RIGHTS~1/RIGHTL~1').
|
121
|
+
once
|
122
|
+
subject.right_link_home_dir.should == 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1'
|
123
|
+
subject.private_bin_dir.should == 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1/bin'
|
124
|
+
subject.sandbox_dir.should == 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox'
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should generate right_link_home_dir when not set in ENV' do
|
128
|
+
@mock_env.should_receive(:[]).with('RS_RIGHT_LINK_HOME').and_return(nil)
|
129
|
+
file_class.
|
130
|
+
should_receive(:normalize_path).
|
131
|
+
with('C:/Program Files (x86)/RightScale/RightLink').
|
132
|
+
and_return('C:/PROGRA~2/RIGHTS~1/RIGHTL~1').
|
133
|
+
once
|
134
|
+
subject.right_link_home_dir.should == 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context '#temp_dir' do
|
139
|
+
it 'should query temp_dir by calling GetTempPath API' do
|
140
|
+
temp_path_from_api = "C:\\Users\\foo\\AppData\\Local\\Temp\\"
|
141
|
+
instrument_get_temp_path_api(temp_path_from_api) { temp_path_from_api.length }
|
142
|
+
subject.temp_dir.should == 'C:/Users/foo/AppData/Local/Temp'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context '#long_path_to_short_path' do
|
147
|
+
it 'should convert existing long path to short path' do
|
148
|
+
long_path = 'C:\Program Files (x86)\RightScale\RightLink'
|
149
|
+
short_path = 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1'
|
150
|
+
instrument_get_short_path_name_api(long_path, short_path) { short_path.length }
|
151
|
+
file_class.should_receive(:exists?).with(long_path).and_return(true).once
|
152
|
+
subject.long_path_to_short_path(long_path).should == short_path
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should convert existing parent of missing long path to short path' do
|
156
|
+
long_path_parent = 'C:/Program Files (x86)/RightScale'
|
157
|
+
long_path = long_path_parent + '/RightLink'
|
158
|
+
short_path_parent = 'C:/PROGRA~2/RIGHTS~1'
|
159
|
+
short_path = short_path_parent + '/RightLink'
|
160
|
+
instrument_get_short_path_name_api(long_path_parent, short_path_parent) { short_path_parent.length }
|
161
|
+
file_class.should_receive(:exists?).with(long_path).and_return(false).once
|
162
|
+
file_class.should_receive(:exists?).with(long_path_parent).and_return(true).once
|
163
|
+
subject.long_path_to_short_path(long_path).should == short_path
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
context '#pretty_path' do
|
168
|
+
it 'should pretty path' do
|
169
|
+
ugly = 'c:\/make//\/me\pretty'
|
170
|
+
pretty_for_ruby = 'c:/make/me/pretty'
|
171
|
+
pretty_for_cmd_exe = 'c:\make\me\pretty'
|
172
|
+
subject.pretty_path(ugly).should == pretty_for_ruby
|
173
|
+
subject.pretty_path(ugly, true).should == pretty_for_cmd_exe
|
174
|
+
subject.pretty_path(pretty_for_ruby) == pretty_for_ruby
|
175
|
+
subject.pretty_path(pretty_for_cmd_exe) == pretty_for_ruby
|
176
|
+
subject.pretty_path(pretty_for_ruby, true) == pretty_for_cmd_exe
|
177
|
+
subject.pretty_path(pretty_for_cmd_exe, true) == pretty_for_cmd_exe
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
context '#ensure_local_drive_path' do
|
182
|
+
before(:each) do
|
183
|
+
flexmock(::ENV).should_receive(:[]).with('HOMEDRIVE').and_return('C:')
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should do nothing if path is already on home drive' do
|
187
|
+
path = 'c:\already\local.txt'
|
188
|
+
subject.ensure_local_drive_path(path, 'foo').should == path
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'should copy file to temp directory if not local' do
|
192
|
+
network_path = 'z:/from/network/drive.txt'
|
193
|
+
local_path = 'c:/temp/foo/drive.txt'
|
194
|
+
subject.should_receive(:temp_dir).and_return('c:/temp')
|
195
|
+
mock_file_utils = flexmock(::FileUtils)
|
196
|
+
mock_file_utils.should_receive(:mkdir_p).with('c:/temp/foo').and_return(true).once
|
197
|
+
file_class.should_receive(:directory?).with(network_path).and_return(false).once
|
198
|
+
mock_file_utils.should_receive(:cp).with(network_path, local_path).and_return(true).once
|
199
|
+
subject.ensure_local_drive_path(network_path, 'foo').should == local_path
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end # paths
|
203
|
+
|
204
|
+
context '#create_symlink' do
|
205
|
+
it 'should create directory symlink' do
|
206
|
+
from_path = 'c:\foo\bar'
|
207
|
+
to_path = 'c:\foo\baz'
|
208
|
+
file_class.should_receive(:directory?).with(from_path).and_return(true)
|
209
|
+
instrument_create_symbolic_link_api(from_path, to_path, 1) { 1 }
|
210
|
+
subject.create_symlink(from_path, to_path).should == 0
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'should create file symlink' do
|
214
|
+
from_path = 'c:\foo\bar.txt'
|
215
|
+
to_path = 'c:\baz\bar.txt'
|
216
|
+
file_class.should_receive(:directory?).with(from_path).and_return(false)
|
217
|
+
instrument_create_symbolic_link_api(from_path, to_path, 0) { 1 }
|
218
|
+
subject.create_symlink(from_path, to_path).should == 0
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should raise Win32Error on failure' do
|
222
|
+
from_path = 'c:\some\file.txt'
|
223
|
+
to_path = 'c:\no_access\hmm.txt'
|
224
|
+
file_class.should_receive(:directory?).with(from_path).and_return(false)
|
225
|
+
instrument_create_symbolic_link_api(from_path, to_path, 0) { 0 }
|
226
|
+
instrument_win32_error(5, 'Access is denied.')
|
227
|
+
expect { subject.create_symlink(from_path, to_path) }.
|
228
|
+
to raise_error(
|
229
|
+
described_class::Win32Error,
|
230
|
+
"Failed to create link from #{from_path.inspect} to #{to_path.inspect}\nWin32 error code = 5\nAccess is denied.")
|
231
|
+
end
|
232
|
+
end # create_symlink
|
233
|
+
end # supports windows platform filesystem
|
234
|
+
|
235
|
+
shared_examples_for 'supports windows platform shell' do
|
236
|
+
# required by 'supports any platform shell'
|
237
|
+
def instrument_booted_at(booted_at)
|
238
|
+
# example:
|
239
|
+
# >echo | wmic OS Get LastBootUpTime 2>&1
|
240
|
+
# LastBootUpTime
|
241
|
+
# 20131025093127.375199-420
|
242
|
+
bat = ::Time.at(booted_at.to_i) # same bat time ...
|
243
|
+
platform_class.
|
244
|
+
should_receive(:execute).
|
245
|
+
with('echo | wmic OS Get LastBootUpTime 2>&1', {}).
|
246
|
+
and_return(
|
247
|
+
'%04d%02d%02d%02d%02d%02d.%06d%03d' %
|
248
|
+
[bat.year, bat.month, bat.day,
|
249
|
+
bat.hour, bat.min, bat.sec,
|
250
|
+
bat.usec, bat.utc_offset / 60]
|
251
|
+
)
|
252
|
+
end
|
253
|
+
|
254
|
+
it_should_behave_like 'supports any platform shell'
|
255
|
+
|
256
|
+
context 'paths' do
|
257
|
+
before(:each) do
|
258
|
+
# win32/dir-based constants.
|
259
|
+
flexmock(platform_class.filesystem).
|
260
|
+
should_receive(:sandbox_dir).
|
261
|
+
and_return('C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox')
|
262
|
+
|
263
|
+
# ENV-based constants.
|
264
|
+
@mock_env = flexmock(::ENV)
|
265
|
+
@mock_env.should_receive(:[]).
|
266
|
+
with('RS_RUBY_EXE').
|
267
|
+
and_return('C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe').
|
268
|
+
by_default
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'should return path constants for windows' do
|
272
|
+
subject.null_output_name.should == 'NUL'
|
273
|
+
file_class.
|
274
|
+
should_receive(:normalize_path).
|
275
|
+
with('C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe').
|
276
|
+
and_return('C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe').
|
277
|
+
once
|
278
|
+
subject.sandbox_ruby.should == 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe'
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'should generate right_link_home_dir when not set in ENV' do
|
282
|
+
@mock_env.should_receive(:[]).with('RS_RUBY_EXE').and_return(nil)
|
283
|
+
file_class.
|
284
|
+
should_receive(:normalize_path).
|
285
|
+
with('C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe').
|
286
|
+
and_return('C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe').
|
287
|
+
once
|
288
|
+
subject.sandbox_ruby.should == 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe'
|
289
|
+
end
|
290
|
+
end # paths
|
291
|
+
|
292
|
+
context 'commands' do
|
293
|
+
context '#format_script_file_name' do
|
294
|
+
let(:pathexts) { %w[.EXE .BAT] }
|
295
|
+
let(:pathext_env) { pathexts.join(';') }
|
296
|
+
|
297
|
+
before(:each) do
|
298
|
+
flexmock(::ENV).should_receive(:[]).with('PATHEXT').and_return(pathext_env)
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'should format for powershell by default' do
|
302
|
+
subject.format_script_file_name('foo').should == 'foo.ps1'
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'should keep extension when executable' do
|
306
|
+
subject.format_script_file_name('foo.bat').should == 'foo.bat'
|
307
|
+
end
|
308
|
+
|
309
|
+
it 'should append default extension when not executable' do
|
310
|
+
subject.format_script_file_name('foo.bar').should == 'foo.bar.ps1'
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
context '#format_executable_command' do
|
315
|
+
it 'should format using given script path' do
|
316
|
+
subject.format_executable_command('foo.bat', 'a/b', 'c d').should == 'foo.bat a/b "c d"'
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'should insert cmd.exe if no extension was given' do
|
320
|
+
subject.format_executable_command('foo', 'bar', '1 2').should == 'cmd.exe /C "foo bar "1 2""'
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
context '#format_shell_command' do
|
325
|
+
it 'should insert powershell.exe when extension is .ps1' do
|
326
|
+
# RightRun runs child processes as 64-bit instead of 32-bit as would be
|
327
|
+
# the default behavior when creating a child process from ruby.exe
|
328
|
+
rrp = "C:\\PROGRA~1\\RIGHTS~1\\Shared\\RightRun.exe"
|
329
|
+
script_path = 'c:\temp\foo.ps1'
|
330
|
+
subject.should_receive(:right_run_path).and_return(rrp)
|
331
|
+
|
332
|
+
# we wrap powershell script execution with additional checks for
|
333
|
+
# $LastExitCode and $Error to ensure user script doesn't fail
|
334
|
+
# mysteriously without any kind of error reporting (i.e. it saves us
|
335
|
+
# some support calls).
|
336
|
+
expected_cmd =
|
337
|
+
"#{rrp} powershell.exe -command \"&{set-executionpolicy -executionPolicy RemoteSigned -Scope Process;" +
|
338
|
+
" &#{script_path} bar; if ($NULL -eq $LastExitCode) { $LastExitCode = 0 };" +
|
339
|
+
' if ((0 -eq $LastExitCode) -and ($Error.Count -gt 0))' +
|
340
|
+
" { $RS_message = 'Script exited successfully but $Error contained '+($Error.Count)+' error(s):';" +
|
341
|
+
" write-output $RS_message; write-output $Error; $LastExitCode = 1 }; exit $LastExitCode}\""
|
342
|
+
|
343
|
+
subject.format_shell_command(script_path, 'bar').should == expected_cmd
|
344
|
+
end
|
345
|
+
|
346
|
+
it 'should insert ruby.exe when extension is .rb' do
|
347
|
+
ruby_exe_path = 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe'
|
348
|
+
subject.should_receive(:sandbox_ruby).and_return(ruby_exe_path)
|
349
|
+
subject.format_shell_command('foo.rb', 'bar').should == "#{ruby_exe_path} foo.rb bar"
|
350
|
+
end
|
351
|
+
|
352
|
+
it 'should format using given script path for other extensions' do
|
353
|
+
subject.format_shell_command('foo.bat', 'a/b', 'c d').should == 'foo.bat a/b "c d"'
|
354
|
+
end
|
355
|
+
|
356
|
+
it 'should insert cmd.exe if no extension was given' do
|
357
|
+
subject.format_shell_command('foo', 'bar', '1 2').should == 'cmd.exe /C "foo bar "1 2""'
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
context '#format_ruby_command' do
|
362
|
+
it 'should format for ruby' do
|
363
|
+
ruby_exe_path = 'C:/PROGRA~2/RIGHTS~1/RIGHTL~1/sandbox/ruby/bin/ruby.exe'
|
364
|
+
subject.should_receive(:sandbox_ruby).and_return(ruby_exe_path)
|
365
|
+
subject.format_ruby_command('foo.rb', 'bar').should == "#{ruby_exe_path} foo.rb bar"
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end # commands
|
369
|
+
end # supports windows platform shell
|
370
|
+
|
371
|
+
shared_examples_for 'supports windows platform controller' do
|
372
|
+
context '#reboot' do
|
373
|
+
it 'should call InitiateSystemShutdown API' do
|
374
|
+
instrument_initiate_system_shutdown_api(true)
|
375
|
+
subject.reboot.should be_true
|
376
|
+
end
|
377
|
+
end # reboot
|
378
|
+
|
379
|
+
context '#shutdown' do
|
380
|
+
it 'should call InitiateSystemShutdown API' do
|
381
|
+
instrument_initiate_system_shutdown_api(false)
|
382
|
+
subject.shutdown.should be_true
|
383
|
+
end
|
384
|
+
end # shutdown
|
385
|
+
end # controller
|
386
|
+
|
387
|
+
shared_examples_for 'supports windows platform installer' do
|
388
|
+
context :install do
|
389
|
+
it 'should raise not implemented' do
|
390
|
+
expect { subject.install(%w[foo bar]) }.
|
391
|
+
to raise_error(
|
392
|
+
::RightScale::Exceptions::PlatformError,
|
393
|
+
'No package installers supported on Windows')
|
394
|
+
end
|
395
|
+
end # install
|
396
|
+
end # supports windows platform installer
|
397
|
+
|
398
|
+
shared_examples_for 'supports windows platform rng' do
|
399
|
+
context '#pseudorandom_bytes' do
|
400
|
+
it 'should generate random bytes using ruby under Windows' do
|
401
|
+
a = subject.pseudorandom_bytes(16)
|
402
|
+
b = subject.pseudorandom_bytes(16)
|
403
|
+
a.bytesize.should == 16
|
404
|
+
b.bytesize.should == 16
|
405
|
+
a.should_not == b # equality is statistically impossible
|
406
|
+
subject.pseudorandom_bytes(256).bytesize.should == 256
|
407
|
+
end
|
408
|
+
end # pseudorandom_bytes
|
409
|
+
end # supports windows platform rng
|
410
|
+
|
411
|
+
shared_examples_for 'supports windows platform process' do
|
412
|
+
context '#resident_set_size' do
|
413
|
+
it 'should return resident set size for current process' do
|
414
|
+
expected_size = 12345
|
415
|
+
instrument_get_process_memory_info_api(expected_size)
|
416
|
+
subject.resident_set_size.should == expected_size
|
417
|
+
end
|
418
|
+
end # pseudorandom_bytes
|
419
|
+
end # supports windows platform rng
|
420
|
+
|
421
|
+
shared_examples_for 'supports windows platform volume manager' do
|
422
|
+
let(:win2003_version) do
|
423
|
+
::RightScale::Platform::WindowsSystemInformation::Version.new(5, 2, 3790)
|
424
|
+
end
|
425
|
+
let(:win2008r2_version) do
|
426
|
+
::RightScale::Platform::WindowsSystemInformation::Version.new(6, 1, 7601)
|
427
|
+
end
|
428
|
+
|
429
|
+
before(:each) do
|
430
|
+
flexmock(platform_class.windows_system_information).
|
431
|
+
should_receive(:version).
|
432
|
+
and_return(win2008r2_version)
|
433
|
+
end
|
434
|
+
|
435
|
+
context :is_attachable_volume_path? do
|
436
|
+
it 'allows paths with hyphens and underscores' do
|
437
|
+
subject.is_attachable_volume_path?('C:\\Some_crazy-path').should == true
|
438
|
+
end
|
439
|
+
|
440
|
+
it 'allows paths with periods' do
|
441
|
+
subject.is_attachable_volume_path?('C:\\Some.crazy.path').should == true
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'allows paths with tildes' do
|
445
|
+
subject.is_attachable_volume_path?('C:\\~Some~crazy~path').should == true
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
context :volumes do
|
450
|
+
let(:volumes_script) do
|
451
|
+
<<EOF
|
452
|
+
rescan
|
453
|
+
list volume
|
454
|
+
EOF
|
455
|
+
end
|
456
|
+
|
457
|
+
it 'can parse volumes from diskpart output' do
|
458
|
+
subject.
|
459
|
+
should_receive(:run_diskpart_script).
|
460
|
+
with(volumes_script, String).
|
461
|
+
and_return(
|
462
|
+
<<EOF
|
463
|
+
Volume ### Ltr Label Fs Type Size Status Info
|
464
|
+
---------- --- ----------- ----- ---------- ------- --------- --------
|
465
|
+
Volume 0 C 2008Boot NTFS Partition 80 GB Healthy System
|
466
|
+
* Volume 1 D NTFS Partition 4094 MB Healthy
|
467
|
+
Volume 2 NTFS Partition 4094 MB Healthy
|
468
|
+
EOF
|
469
|
+
).once
|
470
|
+
expected_volumes = [
|
471
|
+
{ :index => 0, :device => 'C:', :label => '2008Boot', :filesystem => 'NTFS', :type => 'Partition', :total_size => 85899345920, :status => 'Healthy', :info => 'System' },
|
472
|
+
{ :index => 1, :device => 'D:', :label => nil, :filesystem => 'NTFS', :type => 'Partition', :total_size => 4292870144, :status => 'Healthy', :info => nil },
|
473
|
+
{ :index => 2, :device => nil, :label => nil, :filesystem => 'NTFS', :type => 'Partition', :total_size => 4292870144, :status => 'Healthy', :info => nil }
|
474
|
+
]
|
475
|
+
subject.volumes.should == expected_volumes
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'can parse volumes from diskpart output with mounted paths' do
|
479
|
+
subject.
|
480
|
+
should_receive(:run_diskpart_script).
|
481
|
+
with(volumes_script, String).
|
482
|
+
and_return(
|
483
|
+
<<EOF
|
484
|
+
Volume ### Ltr Label Fs Type Size Status Info
|
485
|
+
---------- --- ----------- ----- ---------- ------- --------- --------
|
486
|
+
Volume 0 C NTFS Partition 80 GB Healthy System
|
487
|
+
* Volume 1 FAT32 Partition 1023 MB Healthy
|
488
|
+
C:\\Program Files\\RightScale\\Mount\\Softlayer\\
|
489
|
+
EOF
|
490
|
+
).once
|
491
|
+
expected_volumes = [
|
492
|
+
{ :index => 0, :device => 'C:', :label => nil, :filesystem => 'NTFS', :type => 'Partition', :total_size => 85899345920, :status => 'Healthy', :info => 'System' },
|
493
|
+
{ :index => 1, :device => 'C:\\Program Files\\RightScale\\Mount\\Softlayer\\', :label => nil, :filesystem => 'FAT32', :type => 'Partition', :total_size => 1072693248, :status => 'Healthy', :info => nil }
|
494
|
+
]
|
495
|
+
subject.volumes.should == expected_volumes
|
496
|
+
end
|
497
|
+
|
498
|
+
it 'raises a parser error when diskpart output is malformed' do
|
499
|
+
subject.
|
500
|
+
should_receive(:run_diskpart_script).
|
501
|
+
with(volumes_script, String).
|
502
|
+
and_return('gibberish').
|
503
|
+
once
|
504
|
+
expect { subject.volumes }.
|
505
|
+
to raise_error(RightScale::Platform::VolumeManager::ParserError)
|
506
|
+
end
|
507
|
+
|
508
|
+
it 'can filter results with only one condition' do
|
509
|
+
subject.
|
510
|
+
should_receive(:run_diskpart_script).
|
511
|
+
with(volumes_script, String).
|
512
|
+
and_return(
|
513
|
+
<<EOF
|
514
|
+
Volume ### Ltr Label Fs Type Size Status Info
|
515
|
+
---------- --- ----------- ----- ---------- ------- --------- --------
|
516
|
+
Volume 0 C 2008Boot NTFS Partition 80 GB Healthy System
|
517
|
+
* Volume 1 D NTFS Partition 4094 MB Healthy
|
518
|
+
Volume 2 NTFS Partition 4094 MB Healthy
|
519
|
+
EOF
|
520
|
+
).once
|
521
|
+
expected_volumes = [
|
522
|
+
{ :index => 1, :device => 'D:', :label => nil, :filesystem => 'NTFS', :type => 'Partition', :total_size => 4292870144, :status => 'Healthy', :info => nil }
|
523
|
+
]
|
524
|
+
subject.volumes(:device => 'D:').should == expected_volumes
|
525
|
+
end
|
526
|
+
|
527
|
+
it 'can filter results with many conditions' do
|
528
|
+
subject.
|
529
|
+
should_receive(:run_diskpart_script).
|
530
|
+
with(volumes_script, String).
|
531
|
+
and_return(
|
532
|
+
<<EOF
|
533
|
+
Volume ### Ltr Label Fs Type Size Status Info
|
534
|
+
---------- --- ----------- ----- ---------- ------- --------- --------
|
535
|
+
Volume 0 C 2008Boot NTFS Partition 80 GB Healthy System
|
536
|
+
* Volume 1 D NTFS Partition 4094 MB Healthy
|
537
|
+
Volume 2 NTFS Partition 4094 MB Healthy
|
538
|
+
EOF
|
539
|
+
).once
|
540
|
+
expected_volumes = [
|
541
|
+
{:index => 1, :device => 'D:', :label => nil, :filesystem => 'NTFS', :type => 'Partition', :total_size => 4292870144, :status => 'Healthy', :info => nil}
|
542
|
+
]
|
543
|
+
conditions = { :device => 'D:', :filesystem => 'NTFS', :type => 'Partition' }
|
544
|
+
subject.volumes(conditions).should == expected_volumes
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
context :assign_device do
|
549
|
+
it 'assigns a device to a drive letter when a drive letter is specified' do
|
550
|
+
assign_device_script = <<EOF
|
551
|
+
rescan
|
552
|
+
list volume
|
553
|
+
select volume "0"
|
554
|
+
attribute volume clear readonly noerr
|
555
|
+
|
556
|
+
assign letter=S
|
557
|
+
EOF
|
558
|
+
|
559
|
+
subject.
|
560
|
+
should_receive(:run_diskpart_script).
|
561
|
+
with(assign_device_script, String).
|
562
|
+
and_return('').
|
563
|
+
once
|
564
|
+
subject.assign_device(0, 'S:')
|
565
|
+
end
|
566
|
+
|
567
|
+
it 'assigns a device to a path when a mount point is specified' do
|
568
|
+
assign_device_script = <<EOF
|
569
|
+
rescan
|
570
|
+
list volume
|
571
|
+
select volume "2"
|
572
|
+
attribute volume clear readonly noerr
|
573
|
+
|
574
|
+
assign mount="C:\\Program Files\\RightScale\\Mount\\Softlayer"
|
575
|
+
EOF
|
576
|
+
subject.
|
577
|
+
should_receive(:run_diskpart_script).
|
578
|
+
with(assign_device_script, String).
|
579
|
+
and_return('').
|
580
|
+
once
|
581
|
+
subject.assign_device(2, "C:\\Program Files\\RightScale\\Mount\\Softlayer")
|
582
|
+
end
|
583
|
+
|
584
|
+
it 'raises an exception when an invalid drive letter is specified' do
|
585
|
+
expect { subject.assign_device(0, 'C:') }.
|
586
|
+
to raise_error(RightScale::Platform::VolumeManager::ArgumentError)
|
587
|
+
end
|
588
|
+
|
589
|
+
it 'raises an exception when an invalid path is specified' do
|
590
|
+
expect { subject.assign_device(0, 'This is not a path') }.
|
591
|
+
to raise_error(RightScale::Platform::VolumeManager::ArgumentError)
|
592
|
+
end
|
593
|
+
|
594
|
+
it 'raises an exception when a mount path is specified and OS is pre 2008' do
|
595
|
+
subject.should_receive(:os_version).and_return(win2003_version)
|
596
|
+
expect { subject.assign_device(0, "C:\\Somepath") }.
|
597
|
+
to raise_error(RightScale::Platform::VolumeManager::ArgumentError)
|
598
|
+
end
|
599
|
+
|
600
|
+
it 'does not assign when already assigned by index' do
|
601
|
+
subject.should_receive(:run_diskpart_script).never
|
602
|
+
subject.
|
603
|
+
should_receive(:volumes).
|
604
|
+
and_return([{:index => '0', :device => "C:\\Program Files\\RightScale\\Mount\\Softlayer"}]).
|
605
|
+
once
|
606
|
+
subject.assign_device(0, "C:\\Program Files\\RightScale\\Mount\\Softlayer", :idempotent => true)
|
607
|
+
end
|
608
|
+
|
609
|
+
it 'does not assign when already assigned by device' do
|
610
|
+
subject.should_receive(:run_diskpart_script).never
|
611
|
+
subject.
|
612
|
+
should_receive(:volumes).
|
613
|
+
and_return([{:index => '0', :device => 'Z:'}]).
|
614
|
+
once
|
615
|
+
subject.assign_device('Z:', 'Z:', :idempotent => true)
|
616
|
+
end
|
617
|
+
|
618
|
+
it 'does not clear readonly flag if :clear_readonly option is set to false' do
|
619
|
+
assign_device_script = <<EOF
|
620
|
+
rescan
|
621
|
+
list volume
|
622
|
+
select volume "0"
|
623
|
+
|
624
|
+
|
625
|
+
assign mount="C:\\Program Files\\RightScale\\Mount\\Softlayer"
|
626
|
+
EOF
|
627
|
+
subject.
|
628
|
+
should_receive(:run_diskpart_script).
|
629
|
+
with(assign_device_script, String).
|
630
|
+
and_return('').
|
631
|
+
once
|
632
|
+
subject.assign_device(0, "C:\\Program Files\\RightScale\\Mount\\Softlayer", :clear_readonly => false)
|
633
|
+
end
|
634
|
+
|
635
|
+
it 'removes all previous assignments if :remove_all option is set to true' do
|
636
|
+
assign_device_script = <<EOF
|
637
|
+
rescan
|
638
|
+
list volume
|
639
|
+
select volume "0"
|
640
|
+
attribute volume clear readonly noerr
|
641
|
+
remove all noerr
|
642
|
+
assign mount="C:\\Program Files\\RightScale\\Mount\\Softlayer"
|
643
|
+
EOF
|
644
|
+
subject.
|
645
|
+
should_receive(:run_diskpart_script).
|
646
|
+
with(assign_device_script, String).
|
647
|
+
and_return('').
|
648
|
+
once
|
649
|
+
subject.assign_device(0, "C:\\Program Files\\RightScale\\Mount\\Softlayer", :remove_all => true)
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
context :format_disk do
|
654
|
+
it 'formats and assigns a drive to a drive letter when a drive letter is specified' do
|
655
|
+
assign_device_script = <<EOF
|
656
|
+
rescan
|
657
|
+
list disk
|
658
|
+
select disk 0
|
659
|
+
attribute disk clear readonly noerr
|
660
|
+
online disk noerr
|
661
|
+
clean
|
662
|
+
create partition primary
|
663
|
+
assign letter=S
|
664
|
+
format FS=NTFS quick
|
665
|
+
EOF
|
666
|
+
subject.
|
667
|
+
should_receive(:run_diskpart_script).
|
668
|
+
with(assign_device_script, String).
|
669
|
+
and_return('').
|
670
|
+
once
|
671
|
+
subject.format_disk(0, 'S:')
|
672
|
+
end
|
673
|
+
|
674
|
+
it 'formats and assigns a drive to a path when a mount point is specified' do
|
675
|
+
assign_device_script = <<EOF
|
676
|
+
rescan
|
677
|
+
list disk
|
678
|
+
select disk 0
|
679
|
+
attribute disk clear readonly noerr
|
680
|
+
online disk noerr
|
681
|
+
clean
|
682
|
+
create partition primary
|
683
|
+
assign mount="C:\\Somepath"
|
684
|
+
format FS=NTFS quick
|
685
|
+
EOF
|
686
|
+
subject.
|
687
|
+
should_receive(:run_diskpart_script).
|
688
|
+
with(assign_device_script, String).
|
689
|
+
and_return('').
|
690
|
+
once
|
691
|
+
subject.format_disk(0, 'C:\\Somepath')
|
692
|
+
end
|
693
|
+
|
694
|
+
it 'raises an exception when a mount path is specified and OS is pre 2008' do
|
695
|
+
subject.should_receive(:os_version).and_return(win2003_version)
|
696
|
+
expect { subject.format_disk(0, "C:\\Somepath") }.
|
697
|
+
to raise_error(RightScale::Platform::VolumeManager::ArgumentError)
|
698
|
+
end
|
699
|
+
end # format_disk
|
700
|
+
|
701
|
+
context :online_disk do
|
702
|
+
it 'does not online the disk if the disk is already online' do
|
703
|
+
online_disk_script = <<EOF
|
704
|
+
rescan
|
705
|
+
list disk
|
706
|
+
select disk 0
|
707
|
+
attribute disk clear readonly noerr
|
708
|
+
online disk noerr
|
709
|
+
EOF
|
710
|
+
subject.
|
711
|
+
should_receive(:run_diskpart_script).
|
712
|
+
with(online_disk_script, String).
|
713
|
+
and_return('').
|
714
|
+
once
|
715
|
+
subject.online_disk(0)
|
716
|
+
subject.should_receive(:disks).and_return([{:index => 0, :status => 'Online'}]).once
|
717
|
+
subject.online_disk(0, :idempotent => true)
|
718
|
+
end
|
719
|
+
end
|
720
|
+
end # supports windows platform volume manager
|