right_agent 0.10.8 → 0.10.9

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