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 CHANGED
@@ -46,8 +46,9 @@ directory gemtask.package_dir
46
46
  CLEAN.include(gemtask.package_dir)
47
47
 
48
48
  # == Unit tests == #
49
-
50
- RSPEC_OPTS = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
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)
@@ -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
- result = OperationResult.success("name" => @agent_name,
536
- "identity" => @identity,
537
- "hostname" => Socket.gethostname,
538
- "memory" => Platform.process.resident_set_size,
539
- "version" => AgentConfig.protocol_version,
540
- "brokers" => @broker.stats(reset),
541
- "agent stats" => agent_stats(reset),
542
- "receive stats" => @dispatcher.stats(reset),
543
- "send stats" => @sender.stats(reset),
544
- "last reset time" => @last_stat_reset_time.to_i,
545
- "stat time" => now.to_i,
546
- "service uptime" => (now - @service_start_time).to_i,
547
- "machine uptime" => Platform.shell.uptime)
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
@@ -102,7 +102,9 @@ module RightScale
102
102
  'size' => nil
103
103
  }.to_msgpack(*a)
104
104
  @size = msg.size
105
- msg.sub!(/size\300/) { |m| "size" + @size.to_msgpack }
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 =~ /^[D-Zd-z]:[\/\\]?$/)
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):: device specified for the volume to create
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
- assign letter=#{letter}
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 #{letter}: /Q /V: /FS:NTFS"
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):: device specified for the volume to create
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
- assign letter=#{new_letter}
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}\}) (.\{#{info_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
- create(unpack(data))
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[0] > 127 ? MSGPACK_FIRST_SERIALIZERS : JSON_FIRST_SERIALIZERS
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.9.11'
28
- spec.date = '2012-04-16'
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.1')
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
@@ -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).each.select { |x| x =~ pattern }.count
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.parse(serializer.load(data)).should == 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
- Time.parse(serializer.load(data)).to_i.should == time.to_i
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: 45
4
+ hash: 51
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 9
9
- - 11
10
- version: 0.9.11
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-04-16 00:00:00 -07:00
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: 9
44
+ hash: 13
45
45
  segments:
46
46
  - 0
47
- - 1
48
- version: "0.1"
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