right_agent 0.9.11 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
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