right_agent 0.10.8 → 0.10.9

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.
@@ -114,7 +114,7 @@ module RightScale
114
114
  if exists?
115
115
  open(@pid_file,'r') { |f| content[:pid] = f.read.to_i }
116
116
  open(@cookie_file,'r') do |f|
117
- command_options = YAML.load(f.read) rescue {}
117
+ command_options = (YAML.load(f.read) rescue {}) || {}
118
118
  content.merge!(command_options)
119
119
  end if File.exists?(@cookie_file)
120
120
  end
@@ -468,8 +468,6 @@ EOF
468
468
  # partition has actually been formatted.
469
469
  raise ArgumentError.new("Invalid index = #{disk_index}") unless disk_index >= 0
470
470
  raise ArgumentError.new("Invalid device = #{device}") unless is_attachable_volume_path?(device)
471
- online_command = if @os_info.major < 6; "online noerr"; else; "online disk noerr"; end
472
- clear_readonly_command = if @os_info.major < 6; ""; else; "attribute disk clear readonly noerr"; end
473
471
 
474
472
  # note that Windows 2003 server version of diskpart doesn't support
475
473
  # format so that has to be done separately.
@@ -478,8 +476,8 @@ EOF
478
476
  rescan
479
477
  list disk
480
478
  select disk #{disk_index}
481
- #{clear_readonly_command}
482
- #{online_command}
479
+ #{get_clear_readonly_command('disk')}
480
+ #{get_online_disk_command}
483
481
  clean
484
482
  create partition primary
485
483
  #{get_assign_command_for_device(device)}
@@ -506,6 +504,8 @@ EOF
506
504
  #
507
505
  # === Parameters
508
506
  # disk_index(int):: zero-based disk index
507
+ # options(Hash):: A hash of options which allows different behavior while onlining a drive. Possible options are;
508
+ # :idempotent(Bool) - Checks the current disk statuses before attempting to online the disk. If the drive is already online, it bails out making this method idempotent.
509
509
  #
510
510
  # === Return
511
511
  # always true
@@ -514,22 +514,55 @@ EOF
514
514
  # ArgumentError:: on invalid parameters
515
515
  # VolumeError:: on failure to online disk
516
516
  # ParserError:: on failure to parse volume list
517
- def online_disk(disk_index)
517
+ def online_disk(disk_index, options={})
518
518
  raise ArgumentError.new("Invalid disk_index = #{disk_index}") unless disk_index >= 0
519
- clear_readonly_command = if @os_info.major < 6; ""; else; "attribute disk clear readonly noerr"; end
520
- online_command = if @os_info.major < 6; "online"; else; "online disk noerr"; end
519
+ # Set some defaults for backward compatibility, allow user specified options to override defaults
520
+ options = {:idempotent => false}.merge(options)
521
521
  script = <<EOF
522
522
  rescan
523
523
  list disk
524
524
  select disk #{disk_index}
525
- #{clear_readonly_command}
526
- #{online_command}
525
+ #{get_clear_readonly_command('disk')}
526
+ #{get_online_disk_command}
527
527
  EOF
528
+
529
+ if(options[:idempotent])
530
+ disk = disks(:index => disk_index)
531
+ return true if disk && disk[:status] == "Online"
532
+ end
533
+
528
534
  exit_code, output_text = run_script(script)
529
535
  raise VolumeError.new("Failed to online disk #{disk_index}: exit code = #{exit_code}\n#{script}\n#{output_text}") if exit_code != 0
530
536
  true
531
537
  end
532
538
 
539
+ # Brings the disk given by index offline
540
+ #
541
+ # === Parameters
542
+ # disk_index(int):: zero-based disk index
543
+ #
544
+ # === Return
545
+ # always true
546
+ #
547
+ # === Raise
548
+ # ArgumentError:: on invalid parameters
549
+ # VolumeError:: on failure to online disk
550
+ # ParserError:: on failure to parse volume list
551
+ def offline_disk(disk_index)
552
+ raise ArgumentError.new("Invalid disk_index = #{disk_index}") unless disk_index >= 0
553
+ # Set some defaults for backward compatibility, allow user specified options to override defaults
554
+ script = <<EOF
555
+ rescan
556
+ list disk
557
+ select disk #{disk_index}
558
+ offline disk noerr
559
+ EOF
560
+
561
+ exit_code, output_text = run_script(script)
562
+ raise VolumeError.new("Failed to offline disk #{disk_index}: exit code = #{exit_code}\n#{script}\n#{output_text}") if exit_code != 0
563
+ true
564
+ end
565
+
533
566
  # Assigns the given device name to the volume given by index and clears
534
567
  # the readonly attribute, if necessary. The device must not currently be
535
568
  # in use.
@@ -537,6 +570,10 @@ EOF
537
570
  # === Parameters
538
571
  # volume_device_or_index(int):: old device or zero-based volume index (from volumes list, etc.) to select for assignment.
539
572
  # device(String):: disk letter or mount path specified for the volume to create
573
+ # options(Hash):: A hash of options which allows different behavior while assigning a device. Possible options are:
574
+ # :clear_readonly(Bool) - Set to true by default, since the previous implementation of this method always cleared readonly
575
+ # :remove_all(Bool) - Removes all previously assigned devices and paths, essentially a big RESET button for volume assignment
576
+ # :idempotent(Bool) - Checks the current device assignments before assigning the device according to the specified parameters. If the device is already assigned, it bails out making this method idempotent.
540
577
  #
541
578
  # === Return
542
579
  # always true
@@ -545,7 +582,10 @@ EOF
545
582
  # ArgumentError:: on invalid parameters
546
583
  # VolumeError:: on failure to assign device name
547
584
  # ParserError:: on failure to parse volume list
548
- def assign_device(volume_device_or_index, device)
585
+ def assign_device(volume_device_or_index, device, options={})
586
+ # Set some defaults for backward compatibility, allow user specified options to override defaults
587
+ options = {:clear_readonly => true, :idempotent => false}.merge(options)
588
+
549
589
  if device.match(@assignable_path_regex) && @os_info.major < 6
550
590
  raise ArgumentError.new("Mount path assignment is not supported in this version of windows")
551
591
  end
@@ -556,11 +596,26 @@ EOF
556
596
  raise ArgumentError.new("Invalid volume_device_or_index = #{volume_device_or_index}") unless volume_selector_match
557
597
  volume_selector = volume_selector_match[1]
558
598
  raise ArgumentError.new("Invalid device = #{device}") unless is_attachable_volume_path?(device)
599
+ if(options[:idempotent])
600
+ # Device already assigned?
601
+ vols = volumes
602
+ already_assigned = vols.select do |k,v|
603
+ # The volume is specified by it's index and is already mounted to the specified device/path
604
+ (k == :index && v == volume_device_or_index && vols[:device] == device) ||
605
+ # The volume is specified by it's current device/path assignment and is already mounted to the specified device/path
606
+ (k == :device && v == volume_device_or_index)
607
+ end
608
+
609
+ return true if already_assigned.length > 0
610
+ end
611
+ # Validation ends here, and real stuff starts to happen
612
+
559
613
  script = <<EOF
560
614
  rescan
561
615
  list volume
562
616
  select volume "#{volume_selector}"
563
- attribute volume clear readonly noerr
617
+ #{get_clear_readonly_command('volume') if options[:clear_readonly]}
618
+ #{"remove all noerr" if options[:remove_all]}
564
619
  #{get_assign_command_for_device(device)}
565
620
  EOF
566
621
 
@@ -858,6 +913,25 @@ EOF
858
913
  end
859
914
  end
860
915
 
916
+ # Returns the correct 'online disk' diskpart command based on the OS version
917
+ #
918
+ # === Return
919
+ # result(String):: Either "online noerr" or "online disk noerr" depending upon the OS version
920
+ def get_online_disk_command()
921
+ if @os_info.major < 6; "online noerr" else; "online disk noerr" end
922
+ end
923
+
924
+ # Returns the correct 'attribute disk clear readonly' diskpart command based on the OS version
925
+ #
926
+ # === Parameters
927
+ # object_type(String):: One of "disk" or "volume" to clear read only for
928
+ #
929
+ # === Return
930
+ # result(String):: Either a blank string or "attribute #{object_type} clear readonly noerr" depending upon the OS version
931
+ def get_clear_readonly_command(object_type)
932
+ if @os_info.major < 6; "" else; "attribute #{object_type} clear readonly noerr" end
933
+ end
934
+
861
935
  end # VolumeManager
862
936
 
863
937
  # Provides utilities for formatting executable shell commands, etc.
@@ -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.10.8'
28
- spec.date = '2012-05-10'
27
+ spec.version = '0.10.9'
28
+ spec.date = '2012-06-18'
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'
@@ -139,6 +139,7 @@ rescan
139
139
  list volume
140
140
  select volume "0"
141
141
  attribute volume clear readonly noerr
142
+
142
143
  assign letter=S
143
144
  EOF
144
145
 
@@ -160,6 +161,7 @@ rescan
160
161
  list volume
161
162
  select volume "0"
162
163
  attribute volume clear readonly noerr
164
+
163
165
  assign mount="C:\\Program Files\\RightScale\\Mount\\Softlayer"
164
166
  EOF
165
167
 
@@ -187,6 +189,51 @@ EOF
187
189
  lambda{@platform.volume_manager.assign_device(0, "C:\\Somepath")}.should raise_error(RightScale::Platform::VolumeManager::ArgumentError)
188
190
  @platform.volume_manager.set_osinfo(old_osinfo)
189
191
  end
192
+
193
+ it 'does not assign the device if the device is already assigned' do
194
+ script = <<EOF
195
+ rescan
196
+ list volume
197
+ select volume "0"
198
+ attribute volume clear readonly noerr
199
+
200
+ assign mount="C:\\Program Files\\RightScale\\Mount\\Softlayer"
201
+ EOF
202
+
203
+ flexmock(@platform.volume_manager).should_receive(:run_script).with(script).once.and_return([0, ''])
204
+
205
+ @platform.volume_manager.assign_device('0', "C:\\Program Files\\RightScale\\Mount\\Softlayer")
206
+ flexmock(@platform.volume_manager).should_receive(:volumes).once.and_return({:index => '0', :device => "C:\\Program Files\\RightScale\\Mount\\Softlayer"})
207
+ @platform.volume_manager.assign_device('0', "C:\\Program Files\\RightScale\\Mount\\Softlayer", :idempotent => true)
208
+ end
209
+
210
+ it 'does not clear readonly flag if :clear_readonly option is set to false' do
211
+ script = <<EOF
212
+ rescan
213
+ list volume
214
+ select volume "0"
215
+
216
+
217
+ assign mount="C:\\Program Files\\RightScale\\Mount\\Softlayer"
218
+ EOF
219
+
220
+ flexmock(@platform.volume_manager).should_receive(:run_script).with(script).once.and_return([0, ''])
221
+ @platform.volume_manager.assign_device('0', "C:\\Program Files\\RightScale\\Mount\\Softlayer", {:clear_readonly => false})
222
+ end
223
+
224
+ it 'removes all previous assignments if :remove_all option is set to true' do
225
+ script = <<EOF
226
+ rescan
227
+ list volume
228
+ select volume "0"
229
+ attribute volume clear readonly noerr
230
+ remove all noerr
231
+ assign mount="C:\\Program Files\\RightScale\\Mount\\Softlayer"
232
+ EOF
233
+
234
+ flexmock(@platform.volume_manager).should_receive(:run_script).with(script).once.and_return([0, ''])
235
+ @platform.volume_manager.assign_device('0', "C:\\Program Files\\RightScale\\Mount\\Softlayer", :remove_all => true)
236
+ end
190
237
  end
191
238
 
192
239
  context :format_disk do
@@ -248,6 +295,24 @@ EOF
248
295
  end
249
296
 
250
297
  end
298
+
299
+ context :online_disk do
300
+ it 'does not online the disk if the disk is already online' do
301
+ script = <<EOF
302
+ rescan
303
+ list disk
304
+ select disk 0
305
+ attribute disk clear readonly noerr
306
+ online disk noerr
307
+ EOF
308
+
309
+ flexmock(@platform.volume_manager).should_receive(:run_script).with(script).once.and_return([0, ''])
310
+
311
+ @platform.volume_manager.online_disk(0)
312
+ flexmock(@platform.volume_manager).should_receive(:disks).once.and_return({:index => 0, :status => "Online"})
313
+ @platform.volume_manager.online_disk(0, :idempotent => true)
314
+ end
315
+ end
251
316
  end
252
317
  end
253
318
  end
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: 39
5
- prerelease:
4
+ hash: 37
5
+ prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 10
9
- - 8
10
- version: 0.10.8
9
+ - 9
10
+ version: 0.10.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - Lee Kirchhoff
@@ -17,10 +17,10 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2012-05-10 00:00:00 Z
20
+ date: 2012-06-18 00:00:00 -07:00
21
+ default_executable:
21
22
  dependencies:
22
23
  - !ruby/object:Gem::Dependency
23
- name: right_support
24
24
  version_requirements: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
@@ -31,11 +31,11 @@ dependencies:
31
31
  - 1
32
32
  - 3
33
33
  version: "1.3"
34
- type: :runtime
35
34
  requirement: *id001
35
+ name: right_support
36
36
  prerelease: false
37
+ type: :runtime
37
38
  - !ruby/object:Gem::Dependency
38
- name: right_amqp
39
39
  version_requirements: &id002 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
@@ -46,11 +46,11 @@ dependencies:
46
46
  - 0
47
47
  - 3
48
48
  version: "0.3"
49
- type: :runtime
50
49
  requirement: *id002
50
+ name: right_amqp
51
51
  prerelease: false
52
+ type: :runtime
52
53
  - !ruby/object:Gem::Dependency
53
- name: json
54
54
  version_requirements: &id003 !ruby/object:Gem::Requirement
55
55
  none: false
56
56
  requirements:
@@ -61,11 +61,11 @@ dependencies:
61
61
  - 1
62
62
  - 4
63
63
  version: "1.4"
64
- type: :runtime
65
64
  requirement: *id003
65
+ name: json
66
66
  prerelease: false
67
+ type: :runtime
67
68
  - !ruby/object:Gem::Dependency
68
- name: eventmachine
69
69
  version_requirements: &id004 !ruby/object:Gem::Requirement
70
70
  none: false
71
71
  requirements:
@@ -77,11 +77,11 @@ dependencies:
77
77
  - 12
78
78
  - 10
79
79
  version: 0.12.10
80
- type: :runtime
81
80
  requirement: *id004
81
+ name: eventmachine
82
82
  prerelease: false
83
+ type: :runtime
83
84
  - !ruby/object:Gem::Dependency
84
- name: right_popen
85
85
  version_requirements: &id005 !ruby/object:Gem::Requirement
86
86
  none: false
87
87
  requirements:
@@ -93,11 +93,11 @@ dependencies:
93
93
  - 0
94
94
  - 11
95
95
  version: 1.0.11
96
- type: :runtime
97
96
  requirement: *id005
97
+ name: right_popen
98
98
  prerelease: false
99
+ type: :runtime
99
100
  - !ruby/object:Gem::Dependency
100
- name: msgpack
101
101
  version_requirements: &id006 !ruby/object:Gem::Requirement
102
102
  none: false
103
103
  requirements:
@@ -109,11 +109,11 @@ dependencies:
109
109
  - 4
110
110
  - 4
111
111
  version: 0.4.4
112
- type: :runtime
113
112
  requirement: *id006
113
+ name: msgpack
114
114
  prerelease: false
115
+ type: :runtime
115
116
  - !ruby/object:Gem::Dependency
116
- name: net-ssh
117
117
  version_requirements: &id007 !ruby/object:Gem::Requirement
118
118
  none: false
119
119
  requirements:
@@ -124,9 +124,10 @@ dependencies:
124
124
  - 2
125
125
  - 0
126
126
  version: "2.0"
127
- type: :runtime
128
127
  requirement: *id007
128
+ name: net-ssh
129
129
  prerelease: false
130
+ type: :runtime
130
131
  description: |
131
132
  RightAgent provides a foundation for running an agent on a server to interface
132
133
  in a secure fashion with other agents in the RightScale system. A RightAgent
@@ -290,6 +291,7 @@ files:
290
291
  - spec/spec.win32.opts
291
292
  - spec/spec_helper.rb
292
293
  - spec/tracer_spec.rb
294
+ has_rdoc: true
293
295
  homepage: https://github.com/rightscale/right_agent
294
296
  licenses: []
295
297
 
@@ -324,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
324
326
  requirements: []
325
327
 
326
328
  rubyforge_project:
327
- rubygems_version: 1.8.24
329
+ rubygems_version: 1.3.7
328
330
  signing_key:
329
331
  specification_version: 3
330
332
  summary: Agent for interfacing server with RightScale system