right_agent 0.9.11 → 0.10.2
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/Rakefile +3 -2
- data/lib/right_agent/actors/agent_manager.rb +2 -2
- data/lib/right_agent/agent.rb +26 -14
- data/lib/right_agent/packets.rb +3 -1
- data/lib/right_agent/platform/windows.rb +47 -12
- data/lib/right_agent/serialize/message_pack.rb +6 -1
- data/lib/right_agent/serialize/serializer.rb +1 -1
- data/right_agent.gemspec +8 -3
- data/spec/dispatcher_spec.rb +4 -0
- data/spec/log_spec.rb +1 -1
- data/spec/platform/windows_volume_manager_spec.rb +253 -0
- data/spec/serialize/serializer_spec.rb +6 -2
- data/spec/spec.win32.opts +1 -0
- metadata +10 -8
data/Rakefile
CHANGED
@@ -46,8 +46,9 @@ directory gemtask.package_dir
|
|
46
46
|
CLEAN.include(gemtask.package_dir)
|
47
47
|
|
48
48
|
# == Unit tests == #
|
49
|
-
|
50
|
-
|
49
|
+
spec_opts_file = "\"#{File.dirname(__FILE__)}/spec/spec.opts\""
|
50
|
+
spec_opts_file = "\"#{File.dirname(__FILE__)}/spec/spec.win32.opts\"" if RUBY_PLATFORM =~ /mingw|mswin32/
|
51
|
+
RSPEC_OPTS = ['--options', spec_opts_file]
|
51
52
|
|
52
53
|
desc 'Run unit tests'
|
53
54
|
RSpec::Core::RakeTask.new do |t|
|
@@ -65,7 +65,7 @@ class AgentManager
|
|
65
65
|
#
|
66
66
|
# === Return
|
67
67
|
# (RightScale::OperationResult):: Always returns success
|
68
|
-
def stats(options)
|
68
|
+
def stats(options = {})
|
69
69
|
@agent.stats(RightScale::SerializationHelper.symbolize_keys(options))
|
70
70
|
end
|
71
71
|
|
@@ -80,7 +80,7 @@ class AgentManager
|
|
80
80
|
#
|
81
81
|
# === Return
|
82
82
|
# (OperationResult):: Empty success result or error result with message
|
83
|
-
def profile(options)
|
83
|
+
def profile(options = {})
|
84
84
|
require 'memprof'
|
85
85
|
|
86
86
|
options = RightScale::SerializationHelper.symbolize_keys(options)
|
data/lib/right_agent/agent.rb
CHANGED
@@ -177,7 +177,7 @@ module RightScale
|
|
177
177
|
now = Time.now
|
178
178
|
Log.info("[start] Agent #{@identity} starting; time: #{now.utc}; utc_offset: #{now.utc_offset}")
|
179
179
|
Log.debug("Start options:")
|
180
|
-
log_opts = @options.inject([]){ |t, (k, v)| t << "- #{k}: #{v}" }
|
180
|
+
log_opts = @options.inject([]){ |t, (k, v)| t << "- #{k}: #{v.respond_to?(:each) ? v.inspect : v}" }
|
181
181
|
log_opts.each { |l| Log.debug(l) }
|
182
182
|
|
183
183
|
begin
|
@@ -532,19 +532,23 @@ module RightScale
|
|
532
532
|
def stats(options = {})
|
533
533
|
now = Time.now
|
534
534
|
reset = options[:reset]
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
535
|
+
stats = {
|
536
|
+
"name" => @agent_name,
|
537
|
+
"identity" => @identity,
|
538
|
+
"hostname" => Socket.gethostname,
|
539
|
+
"memory" => Platform.process.resident_set_size,
|
540
|
+
"version" => AgentConfig.protocol_version,
|
541
|
+
"brokers" => @broker.stats(reset),
|
542
|
+
"agent stats" => agent_stats(reset),
|
543
|
+
"receive stats" => @dispatcher.stats(reset),
|
544
|
+
"send stats" => @sender.stats(reset),
|
545
|
+
"last reset time" => @last_stat_reset_time.to_i,
|
546
|
+
"stat time" => now.to_i,
|
547
|
+
"service uptime" => (now - @service_start_time).to_i,
|
548
|
+
"machine uptime" => Platform.shell.uptime
|
549
|
+
}
|
550
|
+
stats["revision"] = @revision if @revision
|
551
|
+
result = OperationResult.success(stats)
|
548
552
|
@last_stat_reset_time = now if reset
|
549
553
|
result
|
550
554
|
end
|
@@ -612,6 +616,7 @@ module RightScale
|
|
612
616
|
@agent_type = parsed_identity.agent_type
|
613
617
|
@agent_name = @options[:agent_name]
|
614
618
|
@stats_routing_key = "stats.#{@agent_type}.#{parsed_identity.base_id}"
|
619
|
+
@revision = revision
|
615
620
|
|
616
621
|
@remaining_setup = {}
|
617
622
|
@all_setup = [:setup_identity_queue]
|
@@ -814,6 +819,13 @@ module RightScale
|
|
814
819
|
yield
|
815
820
|
end
|
816
821
|
|
822
|
+
# Determine current revision of software
|
823
|
+
#
|
824
|
+
# === Return
|
825
|
+
# (String):: Revision of software in displayable format
|
826
|
+
def revision
|
827
|
+
end
|
828
|
+
|
817
829
|
end # Agent
|
818
830
|
|
819
831
|
end # RightScale
|
data/lib/right_agent/packets.rb
CHANGED
@@ -102,7 +102,9 @@ module RightScale
|
|
102
102
|
'size' => nil
|
103
103
|
}.to_msgpack(*a)
|
104
104
|
@size = msg.size
|
105
|
-
|
105
|
+
# For ruby 1.9 size attribute moves from front to back of packet
|
106
|
+
re = RUBY_VERSION < "1.9.0" ? /size\xC0/ : /size\xC0$/
|
107
|
+
msg.sub!(re) { |m| "size" + @size.to_msgpack }
|
106
108
|
msg
|
107
109
|
end
|
108
110
|
|
@@ -327,6 +327,9 @@ module RightScale
|
|
327
327
|
|
328
328
|
def initialize
|
329
329
|
@os_info = OSInformation.new
|
330
|
+
|
331
|
+
@assignable_disk_regex = /^[D-Zd-z]:[\/\\]?$/
|
332
|
+
@assignable_path_regex = /^[A-Za-z]:[\/\\][\/\\\w\s\d\-_\.~]+$/
|
330
333
|
end
|
331
334
|
|
332
335
|
# Determines if the given path is valid for a Windows volume attachemnt
|
@@ -335,7 +338,7 @@ module RightScale
|
|
335
338
|
# === Return
|
336
339
|
# result(Boolean):: true if path is a valid volume root
|
337
340
|
def is_attachable_volume_path?(path)
|
338
|
-
return nil != (path =~
|
341
|
+
return (nil != (path =~ @assignable_disk_regex) || nil != (path =~ @assignable_path_regex))
|
339
342
|
end
|
340
343
|
|
341
344
|
# Gets a list of physical or virtual disks in the form:
|
@@ -448,7 +451,7 @@ EOF
|
|
448
451
|
#
|
449
452
|
# === Parameters
|
450
453
|
# disk_index(int): zero-based disk index (from disks list, etc.)
|
451
|
-
# device(String)::
|
454
|
+
# device(String):: disk letter or mount path specified for the volume to create
|
452
455
|
#
|
453
456
|
# === Return
|
454
457
|
# always true
|
@@ -457,12 +460,14 @@ EOF
|
|
457
460
|
# ArgumentError:: on invalid parameters
|
458
461
|
# VolumeError:: on failure to format
|
459
462
|
def format_disk(disk_index, device)
|
463
|
+
if device.match(@assignable_path_regex) && @os_info.major < 6
|
464
|
+
raise ArgumentError.new("Mount path assignment is not supported in this version of windows")
|
465
|
+
end
|
460
466
|
# note that creating the primary partition automatically creates and
|
461
467
|
# selects a new volume, which can be assigned a letter before the
|
462
468
|
# partition has actually been formatted.
|
463
469
|
raise ArgumentError.new("Invalid index = #{disk_index}") unless disk_index >= 0
|
464
470
|
raise ArgumentError.new("Invalid device = #{device}") unless is_attachable_volume_path?(device)
|
465
|
-
letter = device[0,1]
|
466
471
|
online_command = if @os_info.major < 6; "online noerr"; else; "online disk noerr"; end
|
467
472
|
clear_readonly_command = if @os_info.major < 6; ""; else; "attribute disk clear readonly noerr"; end
|
468
473
|
|
@@ -477,7 +482,7 @@ select disk #{disk_index}
|
|
477
482
|
#{online_command}
|
478
483
|
clean
|
479
484
|
create partition primary
|
480
|
-
|
485
|
+
#{get_assign_command_for_device(device)}
|
481
486
|
#{format_command}
|
482
487
|
EOF
|
483
488
|
exit_code, output_text = run_script(script)
|
@@ -485,7 +490,7 @@ EOF
|
|
485
490
|
|
486
491
|
# must format using command shell's FORMAT command before 2008 server.
|
487
492
|
if @os_info.major < 6
|
488
|
-
command = "echo Y | format #{
|
493
|
+
command = "echo Y | format #{device[0,1]}: /Q /V: /FS:NTFS"
|
489
494
|
output_text = `#{command}`
|
490
495
|
exit_code = $?.exitstatus
|
491
496
|
raise VolumeError.new("Failed to format disk #{disk_index} for device #{device}: exit code = #{exit_code}\n#{output_text}") if exit_code != 0
|
@@ -531,7 +536,7 @@ EOF
|
|
531
536
|
#
|
532
537
|
# === Parameters
|
533
538
|
# volume_device_or_index(int):: old device or zero-based volume index (from volumes list, etc.) to select for assignment.
|
534
|
-
# device(String)::
|
539
|
+
# device(String):: disk letter or mount path specified for the volume to create
|
535
540
|
#
|
536
541
|
# === Return
|
537
542
|
# always true
|
@@ -541,18 +546,24 @@ EOF
|
|
541
546
|
# VolumeError:: on failure to assign device name
|
542
547
|
# ParserError:: on failure to parse volume list
|
543
548
|
def assign_device(volume_device_or_index, device)
|
549
|
+
if device.match(@assignable_path_regex) && @os_info.major < 6
|
550
|
+
raise ArgumentError.new("Mount path assignment is not supported in this version of windows")
|
551
|
+
end
|
552
|
+
# Volume selector for drive letter assignments
|
544
553
|
volume_selector_match = volume_device_or_index.to_s.match(/^([D-Zd-z]|\d+):?$/)
|
554
|
+
# Volume selector for mount path assignments
|
555
|
+
volume_selector_match = volume_device_or_index.to_s.match(@assignable_path_regex) unless volume_selector_match
|
545
556
|
raise ArgumentError.new("Invalid volume_device_or_index = #{volume_device_or_index}") unless volume_selector_match
|
546
557
|
volume_selector = volume_selector_match[1]
|
547
558
|
raise ArgumentError.new("Invalid device = #{device}") unless is_attachable_volume_path?(device)
|
548
|
-
new_letter = device[0,1]
|
549
559
|
script = <<EOF
|
550
560
|
rescan
|
551
561
|
list volume
|
552
|
-
select volume #{volume_selector}
|
562
|
+
select volume "#{volume_selector}"
|
553
563
|
attribute volume clear readonly noerr
|
554
|
-
|
564
|
+
#{get_assign_command_for_device(device)}
|
555
565
|
EOF
|
566
|
+
|
556
567
|
exit_code, output_text = run_script(script)
|
557
568
|
raise VolumeError.new("Failed to assign device \"#{device}\" for volume \"#{volume_device_or_index}\": exit code = #{exit_code}\n#{script}\n#{output_text}") if exit_code != 0
|
558
569
|
true
|
@@ -641,7 +652,8 @@ EOF
|
|
641
652
|
# conditions{Hash):: hash of conditions to match or nil (default)
|
642
653
|
#
|
643
654
|
# === Return
|
644
|
-
# result(Array):: volumes or empty
|
655
|
+
# result(Array):: volumes or empty. Drive letters are appended with ':' even though they aren't
|
656
|
+
# returned that way from diskpart
|
645
657
|
#
|
646
658
|
# === Raise
|
647
659
|
# ParserError:: on failure to parse volume list
|
@@ -657,6 +669,14 @@ EOF
|
|
657
669
|
break
|
658
670
|
end
|
659
671
|
match_data = line.match(line_regex)
|
672
|
+
unless match_data
|
673
|
+
path_match_regex = /([A-Za-z]:[\/\\][\/\\\w\s\d]+)/
|
674
|
+
match_data = line.match(path_match_regex)
|
675
|
+
if match_data
|
676
|
+
result.last[:device] = match_data[1]
|
677
|
+
next
|
678
|
+
end
|
679
|
+
end
|
660
680
|
raise ParserError.new("Failed to parse volume info from #{line.inspect} using #{line_regex.inspect}") unless match_data
|
661
681
|
letter = nil_if_empty(match_data[2])
|
662
682
|
device = "#{letter.upcase}:" if letter
|
@@ -689,8 +709,8 @@ EOF
|
|
689
709
|
info_width = header_match[5].length
|
690
710
|
line_regex_text = "^[\\* ] Volume (\\d[\\d ]\{2\}) ([A-Za-z ]) "\
|
691
711
|
"(.\{#{label_width}\}) (.\{#{filesystem_width}\}) "\
|
692
|
-
"(.\{#{type_width}\}) [ ]?([\\d ]\{3\}\\d) (.?B)
|
693
|
-
"(.\{#{status_width}\})
|
712
|
+
"(.\{#{type_width}\}) [ ]?([\\d ]\{3\}\\d) (.?B)\\s{0,2}"\
|
713
|
+
"(.\{#{status_width}\})\\s{0,2}(.\{0,#{info_width}\})"
|
694
714
|
line_regex = Regexp.compile(line_regex_text)
|
695
715
|
else
|
696
716
|
# one or more lines of ignored headers
|
@@ -823,6 +843,21 @@ EOF
|
|
823
843
|
end
|
824
844
|
end
|
825
845
|
|
846
|
+
# Returns the correct diskpart assignment command for the specified device (either drive letter, or path)
|
847
|
+
#
|
848
|
+
# === Parameters
|
849
|
+
# device(String):: Either a drive letter or mount path
|
850
|
+
#
|
851
|
+
# === Return
|
852
|
+
# result(String):: The correct diskpart assignment command
|
853
|
+
def get_assign_command_for_device(device)
|
854
|
+
if device.match(@assignable_disk_regex)
|
855
|
+
"assign letter=#{device[0,1]}"
|
856
|
+
elsif device.match(@assignable_path_regex)
|
857
|
+
"assign mount=\"#{device}\""
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
826
861
|
end # VolumeManager
|
827
862
|
|
828
863
|
# Provides utilities for formatting executable shell commands, etc.
|
@@ -35,7 +35,12 @@ module MessagePack
|
|
35
35
|
# === Return
|
36
36
|
# obj(Object):: Unserialized object
|
37
37
|
def self.load(data)
|
38
|
-
|
38
|
+
if data.respond_to?(:force_encoding)
|
39
|
+
# For Ruby 1.9 need to ensure that MessagePack receives ASCII-8BIT data
|
40
|
+
create(unpack(data.force_encoding("ASCII-8BIT")))
|
41
|
+
else
|
42
|
+
create(unpack(data))
|
43
|
+
end
|
39
44
|
end
|
40
45
|
|
41
46
|
# Create any msgpack_class objects nested within the unserialized data by calling
|
@@ -141,7 +141,7 @@ module RightScale
|
|
141
141
|
# === Return
|
142
142
|
# (Array):: Ordered serializers
|
143
143
|
def order_serializers(packet)
|
144
|
-
packet
|
144
|
+
packet.getbyte(0) > 127 ? MSGPACK_FIRST_SERIALIZERS : JSON_FIRST_SERIALIZERS
|
145
145
|
end
|
146
146
|
|
147
147
|
end # Serializer
|
data/right_agent.gemspec
CHANGED
@@ -24,8 +24,8 @@ require 'rubygems'
|
|
24
24
|
|
25
25
|
Gem::Specification.new do |spec|
|
26
26
|
spec.name = 'right_agent'
|
27
|
-
spec.version = '0.
|
28
|
-
spec.date = '2012-
|
27
|
+
spec.version = '0.10.2'
|
28
|
+
spec.date = '2012-05-01'
|
29
29
|
spec.authors = ['Lee Kirchhoff', 'Raphael Simon', 'Tony Spataro']
|
30
30
|
spec.email = 'lee@rightscale.com'
|
31
31
|
spec.homepage = 'https://github.com/rightscale/right_agent'
|
@@ -38,13 +38,18 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.require_path = 'lib'
|
39
39
|
|
40
40
|
spec.add_dependency('right_support', '~> 1.3')
|
41
|
-
spec.add_dependency('right_amqp', '~> 0.
|
41
|
+
spec.add_dependency('right_amqp', '~> 0.3')
|
42
42
|
spec.add_dependency('json', ['~> 1.4'])
|
43
43
|
spec.add_dependency('eventmachine', '~> 0.12.10')
|
44
44
|
spec.add_dependency('right_popen', '~> 1.0.11')
|
45
45
|
spec.add_dependency('msgpack', '0.4.4')
|
46
46
|
spec.add_dependency('net-ssh', '~> 2.0')
|
47
47
|
|
48
|
+
if spec.platform.to_s =~ /mswin|mingw/
|
49
|
+
spec.add_dependency('win32-dir', '~> 0.3.5')
|
50
|
+
spec.add_dependency('win32-process', '~> 0.6.1')
|
51
|
+
end
|
52
|
+
|
48
53
|
spec.description = <<-EOF
|
49
54
|
RightAgent provides a foundation for running an agent on a server to interface
|
50
55
|
in a secure fashion with other agents in the RightScale system. A RightAgent
|
data/spec/dispatcher_spec.rb
CHANGED
@@ -337,6 +337,7 @@ describe "RightScale::Dispatcher" do
|
|
337
337
|
EM.run do
|
338
338
|
@agent.should_receive(:options).and_return(:dup_check => true)
|
339
339
|
@dispatcher = RightScale::Dispatcher.new(@agent)
|
340
|
+
@dispatcher.em = EMMock
|
340
341
|
req = RightScale::Request.new('/foo/bar', 'you', :token => "try")
|
341
342
|
@dispatcher.instance_variable_get(:@dispatched).store(req.token)
|
342
343
|
@dispatcher.dispatch(req).should be_nil
|
@@ -349,6 +350,7 @@ describe "RightScale::Dispatcher" do
|
|
349
350
|
EM.run do
|
350
351
|
@agent.should_receive(:options).and_return(:dup_check => true)
|
351
352
|
@dispatcher = RightScale::Dispatcher.new(@agent)
|
353
|
+
@dispatcher.em = EMMock
|
352
354
|
req = RightScale::Request.new('/foo/bar', 'you', :token => "try")
|
353
355
|
req.tries.concat(["try1", "try2"])
|
354
356
|
@dispatcher.instance_variable_get(:@dispatched).store("try2")
|
@@ -361,6 +363,7 @@ describe "RightScale::Dispatcher" do
|
|
361
363
|
EM.run do
|
362
364
|
@agent.should_receive(:options).and_return(:dup_check => true)
|
363
365
|
@dispatcher = RightScale::Dispatcher.new(@agent)
|
366
|
+
@dispatcher.em = EMMock
|
364
367
|
req = RightScale::Request.new('/foo/bar', 'you', :token => "try")
|
365
368
|
req.tries.concat(["try1", "try2"])
|
366
369
|
@dispatcher.instance_variable_get(:@dispatched).store("try3")
|
@@ -372,6 +375,7 @@ describe "RightScale::Dispatcher" do
|
|
372
375
|
it "should not check for duplicates if dup_check disabled" do
|
373
376
|
EM.run do
|
374
377
|
@dispatcher = RightScale::Dispatcher.new(@agent)
|
378
|
+
@dispatcher.em = EMMock
|
375
379
|
req = RightScale::Request.new('/foo/bar', 'you', :token => "try")
|
376
380
|
req.tries.concat(["try1", "try2"])
|
377
381
|
@dispatcher.instance_variable_get(:@dispatched).should be_nil
|
data/spec/log_spec.rb
CHANGED
@@ -35,7 +35,7 @@ describe RightScale::Log do
|
|
35
35
|
def log_count(text)
|
36
36
|
# no such animal as egrep in windows, so hacked up an equivalent here.
|
37
37
|
pattern = Regexp.compile(text)
|
38
|
-
File.read(@log_file).
|
38
|
+
File.read(@log_file).each_line.select { |x| x =~ pattern }.count
|
39
39
|
end
|
40
40
|
|
41
41
|
before(:all) do
|
@@ -0,0 +1,253 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2012 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(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
24
|
+
|
25
|
+
if RightScale::Platform.windows?
|
26
|
+
module OsInfoExtensions
|
27
|
+
def set_osinfo(osinfo)
|
28
|
+
@os_info = osinfo
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_osinfo
|
32
|
+
@os_info
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe RightScale::Platform do
|
37
|
+
before(:all) do
|
38
|
+
@platform = RightScale::Platform
|
39
|
+
end
|
40
|
+
|
41
|
+
context :volume_manager do
|
42
|
+
context :is_attachable_volume_path do
|
43
|
+
it 'allows paths with hyphens and underscores' do
|
44
|
+
@platform.volume_manager.is_attachable_volume_path?('C:\\Some_crazy-path').should == true
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'allows paths with periods' do
|
48
|
+
@platform.volume_manager.is_attachable_volume_path?('C:\\Some.crazy.path').should == true
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'allows paths with tildes' do
|
52
|
+
@platform.volume_manager.is_attachable_volume_path?('C:\\~Some~crazy~path').should == true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context :parse_volumes do
|
57
|
+
it 'can parse volumes from diskpart output' do
|
58
|
+
list_vol_resp = <<EOF
|
59
|
+
Volume ### Ltr Label Fs Type Size Status Info
|
60
|
+
---------- --- ----------- ----- ---------- ------- --------- --------
|
61
|
+
Volume 0 C 2008Boot NTFS Partition 80 GB Healthy System
|
62
|
+
* Volume 1 D NTFS Partition 4094 MB Healthy
|
63
|
+
Volume 2 NTFS Partition 4094 MB Healthy
|
64
|
+
EOF
|
65
|
+
|
66
|
+
volume_hash_ary = [
|
67
|
+
{:index => 0, :device => "C:", :label => "2008Boot", :filesystem => "NTFS", :type => "Partition", :total_size => 85899345920, :status => "Healthy", :info => "System"},
|
68
|
+
{:index => 1, :device => "D:", :label => nil, :filesystem => "NTFS", :type => "Partition", :total_size => 4292870144, :status => "Healthy", :info => nil},
|
69
|
+
{:index => 2, :device => nil, :label => nil, :filesystem => "NTFS", :type => "Partition", :total_size => 4292870144, :status => "Healthy", :info => nil}
|
70
|
+
]
|
71
|
+
|
72
|
+
@platform.volume_manager.send(:parse_volumes, list_vol_resp).should == volume_hash_ary
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'can parse volumes from diskpart output with mounted paths' do
|
76
|
+
list_vol_resp = <<EOF
|
77
|
+
Volume ### Ltr Label Fs Type Size Status Info
|
78
|
+
---------- --- ----------- ----- ---------- ------- --------- --------
|
79
|
+
Volume 0 C NTFS Partition 80 GB Healthy System
|
80
|
+
* Volume 1 FAT32 Partition 1023 MB Healthy
|
81
|
+
C:\\Program Files\\RightScale\\Mount\\Softlayer\\
|
82
|
+
EOF
|
83
|
+
|
84
|
+
volume_hash_ary = [
|
85
|
+
{:index => 0, :device => "C:", :label => nil, :filesystem => "NTFS", :type => "Partition", :total_size => 85899345920, :status => "Healthy", :info => "System"},
|
86
|
+
{:index => 1, :device => "C:\\Program Files\\RightScale\\Mount\\Softlayer\\", :label => nil, :filesystem => "FAT32", :type => "Partition", :total_size => 1072693248, :status => "Healthy", :info => nil}
|
87
|
+
]
|
88
|
+
|
89
|
+
@platform.volume_manager.send(:parse_volumes, list_vol_resp).should == volume_hash_ary
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'raises a parser error when diskpart output is malformed' do
|
93
|
+
list_vol_resp = "foobarbaz"
|
94
|
+
|
95
|
+
lambda { @platform.volume_manager.send(:parse_volumes, list_vol_resp) }.should raise_error(RightScale::Platform::VolumeManager::ParserError)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'can filter results with only one condition' do
|
99
|
+
list_vol_resp = <<EOF
|
100
|
+
Volume ### Ltr Label Fs Type Size Status Info
|
101
|
+
---------- --- ----------- ----- ---------- ------- --------- --------
|
102
|
+
Volume 0 C 2008Boot NTFS Partition 80 GB Healthy System
|
103
|
+
* Volume 1 D NTFS Partition 4094 MB Healthy
|
104
|
+
Volume 2 NTFS Partition 4094 MB Healthy
|
105
|
+
EOF
|
106
|
+
|
107
|
+
volume_hash_ary = [
|
108
|
+
{:index => 1, :device => "D:", :label => nil, :filesystem => "NTFS", :type => "Partition", :total_size => 4292870144, :status => "Healthy", :info => nil}
|
109
|
+
]
|
110
|
+
|
111
|
+
condition = {:device => "D:"}
|
112
|
+
|
113
|
+
@platform.volume_manager.send(:parse_volumes, list_vol_resp, condition).should == volume_hash_ary
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'can filter results with many conditions' do
|
117
|
+
list_vol_resp = <<EOF
|
118
|
+
Volume ### Ltr Label Fs Type Size Status Info
|
119
|
+
---------- --- ----------- ----- ---------- ------- --------- --------
|
120
|
+
Volume 0 C 2008Boot NTFS Partition 80 GB Healthy System
|
121
|
+
* Volume 1 D NTFS Partition 4094 MB Healthy
|
122
|
+
Volume 2 NTFS Partition 4094 MB Healthy
|
123
|
+
EOF
|
124
|
+
|
125
|
+
volume_hash_ary = [
|
126
|
+
{:index => 1, :device => "D:", :label => nil, :filesystem => "NTFS", :type => "Partition", :total_size => 4292870144, :status => "Healthy", :info => nil}
|
127
|
+
]
|
128
|
+
|
129
|
+
condition = {:device => "D:", :filesystem => "NTFS", :type => "Partition"}
|
130
|
+
|
131
|
+
@platform.volume_manager.send(:parse_volumes, list_vol_resp, condition).should == volume_hash_ary
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context :assign_device do
|
136
|
+
it 'assigns a device to a drive letter when a drive letter is specified' do
|
137
|
+
script = <<EOF
|
138
|
+
rescan
|
139
|
+
list volume
|
140
|
+
select volume "0"
|
141
|
+
attribute volume clear readonly noerr
|
142
|
+
assign letter=S
|
143
|
+
EOF
|
144
|
+
|
145
|
+
mount_resp = ''
|
146
|
+
flexmock(@platform.volume_manager).should_receive(:run_script).with(script).once.and_return([0, mount_resp])
|
147
|
+
|
148
|
+
@platform.volume_manager.assign_device('0', 'S:')
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'assigns a device to a path when a mount point is specified' do
|
152
|
+
osinfo = flexmock(:major => 6)
|
153
|
+
|
154
|
+
@platform.volume_manager.extend(OsInfoExtensions)
|
155
|
+
old_osinfo = @platform.volume_manager.get_osinfo
|
156
|
+
@platform.volume_manager.set_osinfo(osinfo)
|
157
|
+
|
158
|
+
script = <<EOF
|
159
|
+
rescan
|
160
|
+
list volume
|
161
|
+
select volume "0"
|
162
|
+
attribute volume clear readonly noerr
|
163
|
+
assign mount="C:\\Program Files\\RightScale\\Mount\\Softlayer"
|
164
|
+
EOF
|
165
|
+
|
166
|
+
flexmock(@platform.volume_manager).should_receive(:run_script).with(script).once.and_return([0, ''])
|
167
|
+
|
168
|
+
@platform.volume_manager.assign_device('0', "C:\\Program Files\\RightScale\\Mount\\Softlayer")
|
169
|
+
@platform.volume_manager.set_osinfo(old_osinfo)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'raises an exception when an invalid drive letter is specified' do
|
173
|
+
lambda{@platform.volume_manager.assign_device('0', 'C:')}.should raise_error(RightScale::Platform::VolumeManager::ArgumentError)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'raises an exception when an invalid path is specified' do
|
177
|
+
lambda{@platform.volume_manager.assign_device('0', 'This is not a path')}.should raise_error(RightScale::Platform::VolumeManager::ArgumentError)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'raises an exception when a mount path is specified and OS is pre 2008' do
|
181
|
+
osinfo = flexmock(:major => 5)
|
182
|
+
|
183
|
+
@platform.volume_manager.extend(OsInfoExtensions)
|
184
|
+
old_osinfo = @platform.volume_manager.get_osinfo
|
185
|
+
@platform.volume_manager.set_osinfo(osinfo)
|
186
|
+
|
187
|
+
lambda{@platform.volume_manager.assign_device(0, "C:\\Somepath")}.should raise_error(RightScale::Platform::VolumeManager::ArgumentError)
|
188
|
+
@platform.volume_manager.set_osinfo(old_osinfo)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
context :format_disk do
|
193
|
+
it 'formats and assigns a drive to a drive letter when a drive letter is specified' do
|
194
|
+
osinfo = flexmock(:major => 6)
|
195
|
+
@platform.volume_manager.extend(OsInfoExtensions)
|
196
|
+
old_osinfo = @platform.volume_manager.get_osinfo
|
197
|
+
@platform.volume_manager.set_osinfo(osinfo)
|
198
|
+
|
199
|
+
script = <<EOF
|
200
|
+
rescan
|
201
|
+
list disk
|
202
|
+
select disk 0
|
203
|
+
attribute disk clear readonly noerr
|
204
|
+
online disk noerr
|
205
|
+
clean
|
206
|
+
create partition primary
|
207
|
+
assign letter=S
|
208
|
+
format FS=NTFS quick
|
209
|
+
EOF
|
210
|
+
|
211
|
+
flexmock(@platform.volume_manager).should_receive(:run_script).with(script).once.and_return([0,''])
|
212
|
+
@platform.volume_manager.format_disk(0, 'S:')
|
213
|
+
@platform.volume_manager.set_osinfo(old_osinfo)
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'formats and assigns a drive to a path when a mount point is specified' do
|
217
|
+
osinfo = flexmock(:major => 6)
|
218
|
+
@platform.volume_manager.extend(OsInfoExtensions)
|
219
|
+
old_osinfo = @platform.volume_manager.get_osinfo
|
220
|
+
@platform.volume_manager.set_osinfo(osinfo)
|
221
|
+
|
222
|
+
script = <<EOF
|
223
|
+
rescan
|
224
|
+
list disk
|
225
|
+
select disk 0
|
226
|
+
attribute disk clear readonly noerr
|
227
|
+
online disk noerr
|
228
|
+
clean
|
229
|
+
create partition primary
|
230
|
+
assign mount="C:\\Somepath"
|
231
|
+
format FS=NTFS quick
|
232
|
+
EOF
|
233
|
+
|
234
|
+
flexmock(@platform.volume_manager).should_receive(:run_script).with(script).once.and_return([0,''])
|
235
|
+
@platform.volume_manager.format_disk(0, 'C:\\Somepath')
|
236
|
+
@platform.volume_manager.set_osinfo(old_osinfo)
|
237
|
+
end
|
238
|
+
|
239
|
+
it 'raises an exception when a mount path is specified and OS is pre 2008' do
|
240
|
+
osinfo = flexmock(:major => 5)
|
241
|
+
|
242
|
+
@platform.volume_manager.extend(OsInfoExtensions)
|
243
|
+
old_osinfo = @platform.volume_manager.get_osinfo
|
244
|
+
@platform.volume_manager.set_osinfo(osinfo)
|
245
|
+
|
246
|
+
lambda{@platform.volume_manager.format_disk(0, "C:\\Somepath")}.should raise_error(RightScale::Platform::VolumeManager::ArgumentError)
|
247
|
+
@platform.volume_manager.set_osinfo(old_osinfo)
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
@@ -104,14 +104,18 @@ describe RightScale::Serializer do
|
|
104
104
|
serializer = RightScale::Serializer.new(:msgpack)
|
105
105
|
date = Date.today
|
106
106
|
data = serializer.dump(date)
|
107
|
-
Date.
|
107
|
+
Date.strptime(serializer.load(data), "%Y-%m-%d").should == date
|
108
108
|
end
|
109
109
|
|
110
110
|
it "should serialize Time object" do
|
111
111
|
serializer = RightScale::Serializer.new(:msgpack)
|
112
112
|
time = Time.now
|
113
113
|
data = serializer.dump(time)
|
114
|
-
|
114
|
+
if RUBY_VERSION < "1.9.0"
|
115
|
+
Time.parse(serializer.load(data)).to_i.should == time.to_i
|
116
|
+
else
|
117
|
+
DateTime.parse(serializer.load(data)).to_time.to_i.should == time.to_i
|
118
|
+
end
|
115
119
|
end
|
116
120
|
|
117
121
|
it "should serialize DateTime object" do
|
@@ -0,0 +1 @@
|
|
1
|
+
--format=nested
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 51
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 10
|
9
|
+
- 2
|
10
|
+
version: 0.10.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Lee Kirchhoff
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2012-
|
20
|
+
date: 2012-05-01 00:00:00 -07:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|
@@ -41,11 +41,11 @@ dependencies:
|
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
43
43
|
- !ruby/object:Gem::Version
|
44
|
-
hash:
|
44
|
+
hash: 13
|
45
45
|
segments:
|
46
46
|
- 0
|
47
|
-
-
|
48
|
-
version: "0.
|
47
|
+
- 3
|
48
|
+
version: "0.3"
|
49
49
|
requirement: *id002
|
50
50
|
name: right_amqp
|
51
51
|
prerelease: false
|
@@ -271,6 +271,7 @@ files:
|
|
271
271
|
- spec/platform/linux_volume_manager_spec.rb
|
272
272
|
- spec/platform/platform_spec.rb
|
273
273
|
- spec/platform/windows.rb
|
274
|
+
- spec/platform/windows_volume_manager_spec.rb
|
274
275
|
- spec/results_mock.rb
|
275
276
|
- spec/secure_identity_spec.rb
|
276
277
|
- spec/security/cached_certificate_store_proxy_spec.rb
|
@@ -287,6 +288,7 @@ files:
|
|
287
288
|
- spec/serialize/serializable_spec.rb
|
288
289
|
- spec/serialize/serializer_spec.rb
|
289
290
|
- spec/spec.opts
|
291
|
+
- spec/spec.win32.opts
|
290
292
|
- spec/spec_helper.rb
|
291
293
|
- spec/tracer_spec.rb
|
292
294
|
has_rdoc: true
|