elesai 0.9.3 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/elesai/lsi.rb CHANGED
@@ -1,6 +1,8 @@
1
+ require 'elesai/megacli'
2
+
1
3
  module Elesai
2
4
 
3
- class LSIArray
5
+ class LSI
4
6
 
5
7
  attr_reader :adapters, :virtualdrives, :physicaldrives, :bbus, :enclosures
6
8
 
@@ -13,54 +15,58 @@ module Elesai
13
15
  @bbus = []
14
16
 
15
17
  case opts[:hint]
16
- when :pd,:physicaldrive
17
- PDlist_aAll.new.parse!(self,opts)
18
- when :vd,:virtualdrive
19
- LDPDinfo_aAll.new.parse!(self,opts)
18
+ when :physicaldrive
19
+ Megacli::PDlist_aAll.new.parse!(self,opts)
20
+ when :virtualdrive
21
+ Megacli::LDPDinfo_aAll.new.parse!(self,opts)
22
+ when :adapter
23
+ Megacli::AdpAllInfo_aAll.new.parse!(self,opts)
20
24
  when :bbu
21
- AdpBbuCmd_aAll.new.parse!(self,opts)
25
+ Megacli::AdpBbuCmd_aAll.new.parse!(self,opts)
22
26
  else
23
- PDlist_aAll.new.parse!(self,opts)
24
- LDPDinfo_aAll.new.parse!(self,opts)
25
- AdpBbuCmd_aAll.new.parse!(self,opts)
27
+ Megacli::AdpAllInfo_aAll.new.parse!(self,opts)
28
+ Megacli::PDlist_aAll.new.parse!(self,opts)
29
+ Megacli::LDPDinfo_aAll.new.parse!(self,opts)
30
+ Megacli::AdpBbuCmd_aAll.new.parse!(self,opts)
26
31
  end
27
32
  end
28
33
 
29
- def add_adapter(a)
30
- @adapters[a[:id]] = a if @adapters[a[:id]].nil?
34
+ def add(component)
35
+ case component
36
+ when Adapter
37
+ @adapters[component[:id]] = component if @adapters[component[:id]].nil?
38
+ when VirtualDrive
39
+ @virtualdrives.push(component)
40
+ when PhysicalDrive
41
+ @physicaldrives[component._id] = component if @physicaldrives[component._id].nil?
42
+ return @physicaldrives[component._id]
43
+ when BBU
44
+ @bbus.push(component)
45
+ else
46
+ raise StandardError, "invalid component #{component.class}"
47
+ end
31
48
  end
32
49
 
33
- def add_virtualdrive(vd)
34
- @virtualdrives.push(vd)
35
- end
36
50
 
37
- def add_physicaldrive(pd)
38
- @physicaldrives[pd._id] = pd if @physicaldrives[pd._id].nil?
39
- @physicaldrives[pd._id]
40
- end
41
51
 
42
- def add_bbu(bbu)
43
- @bbus.push(bbu)
44
- end
45
52
 
46
- def to_s
47
- lsiarrayout = "LSI Array\n"
48
- @adapters.each do |adapter|
49
- lsiarrayout += " adapter #{adapter.id}\n"
50
- adapter.virtualdrives.each do |virtualdrive|
51
- lsiarrayout += " +--+ #{virtualdrive.to_str}\n"
52
- virtualdrive.physicaldrives.each do |id,physicaldrive|
53
- lsiarrayout += " | |-- pd #{physicaldrive.to_str}\n"
54
- end
55
- end
56
- end
57
- lsiarrayout
58
- end
59
53
 
60
- ### Adapter
54
+
55
+
56
+
61
57
 
62
58
  class Adapter < Hash
63
59
 
60
+ class Section < Hash
61
+ attr_reader :section
62
+ def initialize(section)
63
+ @section = section
64
+ end
65
+ def inspect
66
+ "#{self.class}:#@section:#{self.__id__}"
67
+ end
68
+ end
69
+
64
70
  def initialize
65
71
  self[:virtualdrives] = []
66
72
  self[:physicaldrives] = {}
@@ -71,14 +77,6 @@ module Elesai
71
77
  "#{self[:id]}"
72
78
  end
73
79
 
74
- def type
75
- :adapter
76
- end
77
-
78
- def type_of?(type)
79
- self.type == type
80
- end
81
-
82
80
  def inspect
83
81
  "#{self.class}:#{self.__id__}"
84
82
  end
@@ -87,9 +85,15 @@ module Elesai
87
85
  self[:physicaldrives][pd._id] = pd unless self[:physicaldrives][pd._id].nil?
88
86
  end
89
87
 
90
- end
88
+ def add_section(section)
89
+ self[section.section] = section
90
+ end
91
+
92
+ def to_s
93
+ "[ADAPTER] %2s %s %s %s %s" % [ self._id,self[:versions][:productname].gsub(/\s+/,'_'),self[:versions][:fwpackagebuild],self[:imageversions][:fwversion],self[:hwconfiguration][:sasaddress] ]
94
+ end
91
95
 
92
- ### Virtual Drive
96
+ end
93
97
 
94
98
  class VirtualDrive < Hash
95
99
 
@@ -116,14 +120,6 @@ module Elesai
116
120
  self[:targetid]
117
121
  end
118
122
 
119
- def type
120
- :virtualdrive
121
- end
122
-
123
- def type_of?(type)
124
- self.type == type
125
- end
126
-
127
123
  def inspect
128
124
  "#{self.class}:#{self.__id__}"
129
125
  end
@@ -138,8 +134,6 @@ module Elesai
138
134
 
139
135
  end
140
136
 
141
- ### Physical Drive
142
-
143
137
  class PhysicalDrive < Hash
144
138
 
145
139
  STATES = {
@@ -175,14 +169,6 @@ module Elesai
175
169
  "e#{self[:enclosuredeviceid].to_s}s#{self[:slotnumber].to_s}".to_sym
176
170
  end
177
171
 
178
- def type
179
- :physicaldrive
180
- end
181
-
182
- def type_of?(type)
183
- self.type == type
184
- end
185
-
186
172
  def to_s
187
173
  keys = [:deviceid, :firmwarestate, :coercedsize, :mediatype, :pdtype, :mediaerrorcount, :predictivefailurecount,:inquirydata]
188
174
  #"[PD] %8s %4s %19s %8.2f%s %5s %5s %3d %3d %s" % [ self.id, @deviceid, "#{@state}:#{@spin}", @_size.number, @_size.unit, @mediatype, @pdtype, @mediaerrors, @predictivefailure, @inquirydata ]
@@ -214,49 +200,41 @@ module Elesai
214
200
  end
215
201
  end
216
202
 
217
- ### BBU
218
-
219
203
  class BBU < Hash
220
204
 
221
205
  class NumberUnit < Struct.new(:number, :unit)
222
206
  def to_s ; "%d%s" % [self.number,self.unit] end
223
207
  end
224
208
 
225
- class Stub < Hash
209
+ class Section < Hash
210
+ attr_reader :section
211
+ def initialize(section)
212
+ @section = section
213
+ end
226
214
  def inspect
227
- "#{self.class}:#{self.__id__}"
215
+ "#{self.class}:#{@section.capitalize}:#{self.__id__}"
228
216
  end
229
217
  end
230
- class Status < Stub; end
231
- class FirmwareStatus < Stub; end
232
- class DesignInfo < Stub; end
233
- class Properties < Stub; end
234
- class CapacityInfo < Stub; end
235
- class GasGaugeStatus < Stub; end
236
218
 
237
219
  def initialize
238
- self[:status] = Status.new
239
- self[:firmwarestatus] = FirmwareStatus.new
240
- self[:designinfo] = DesignInfo.new
241
- self[:properties] = Properties.new
242
- self[:capacityinfo] = CapacityInfo.new
243
- self[:gasgaugestatus] = GasGaugeStatus.new
244
- self[:capacityinfo][:absolutestateofcharge] = '-'
245
220
  end
246
221
 
247
222
  def _id
248
223
  self[:id]
249
224
  end
250
225
 
226
+ def add_section(section)
227
+ self[section.section] = section
228
+ end
229
+
251
230
  def inspect
252
231
  "#{self.class}:#{self.__id__}"
253
232
  end
254
233
 
255
234
  def to_s
256
- self[:capacityinfo][:absolutestateofcharge] = '-' unless self[:batterytype] == "iBBU"
257
- self[:capacityinfo][:remainingcapacity] = '-' unless self[:batterytype] == "iBBU"
258
- "[BBU] %s %-5s %-4s %-11s %3s:%-8s %s:%s %s:%s %7s:%-4s %s" % [self[:id],self[:batterytype],self[:designinfo][:devicechemistry],self[:firmwarestatus][:chargingstatus],self[:firmwarestatus][:learncycleactive],self[:firmwarestatus][:learncyclestatus],self[:voltage].gsub(/\s/,''),self[:firmwarestatus][:voltage],self[:temperature].gsub(/\s/,''),self[:firmwarestatus][:temperature],self[:capacityinfo][:remainingcapacity],self[:capacityinfo][:absolutestateofcharge],self[:properties][:nextlearntime]]
259
- #puts self[:firmwarestatus].keys
235
+ capacityinfo_absolutestateofcharge = self[:batterytype] == 'iBBU' ? self[:capacityinfo][:absolutestateofcharge] : '-'
236
+ capacityinfo_remainingcapacity = self[:batterytype] == 'iBBU' ? self[:capacityinfo][:remainingcapacity] : '-'
237
+ "[BBU] %s %-5s %-4s %-11s %3s:%-8s %s:%s %s:%s %7s:%-4s %s" % [self[:id],self[:batterytype],self[:designinfo][:devicechemistry],self[:firmwarestatus][:chargingstatus],self[:firmwarestatus][:learncycleactive],self[:firmwarestatus][:learncyclestatus],self[:voltage].gsub(/\s/,''),self[:firmwarestatus][:voltage],self[:temperature].gsub(/\s/,''),self[:firmwarestatus][:temperature],capacityinfo_remainingcapacity,capacityinfo_absolutestateofcharge,self[:properties][:nextlearntime]]
260
238
  end
261
239
  end
262
240
  end
@@ -0,0 +1,102 @@
1
+ module Elesai; module Megacli
2
+
3
+ class AdpAllInfo_aAll < Megacli
4
+
5
+ def initialize
6
+ @megacli = { :adapter => { :re => /^Adapter\s+#*(?<value>\d+)/, :method => self.method(:adapter_match) },
7
+ :versions => { :re => /^Versions/, :method => self.method(:section_match) },
8
+ :mfgdata => { :re => /^Mfg\.\s+Data/, :method => self.method(:section_match) },
9
+ :imageversions => { :re => /^Image Versions in Flash/, :method => self.method(:section_match) },
10
+ :pendingvensions => { :re => /^Pending Images in Flash/, :method => self.method(:section_match) },
11
+ :pciinfo => { :re => /^PCI Info/, :method => self.method(:section_match) },
12
+ :hwconfiguration => { :re => /^HW Configuration/, :method => self.method(:section_match) },
13
+ :setttings => { :re => /^Settings/, :method => self.method(:section_match) },
14
+ :capabilities => { :re => /^Capabilities/, :method => self.method(:section_match) },
15
+ :status => { :re => /^Status/, :method => self.method(:section_match) },
16
+ :limitations => { :re => /^Limitations/, :method => self.method(:section_match) },
17
+ :devicepresent => { :re => /^Device Present/, :method => self.method(:section_match) },
18
+ :supportedadapteroperations => { :re => /^Supported Adapter Operations/, :method => self.method(:section_match) },
19
+ :supportedvdoperations => { :re => /^Supported VD Operations/, :method => self.method(:section_match) },
20
+ :supportedddoperations => { :re => /^Supported PD Operations/, :method => self.method(:section_match) },
21
+ :errorcounters => { :re => /^Error Counters/, :method => self.method(:section_match) },
22
+ :clusterinformation => { :re => /^ClusterInformation/, :method => self.method(:section_match) },
23
+ :defaultsettings => { :re => /^Default Settings/, :method => self.method(:section_match) },
24
+ :exit => { :re => /^Exit Code: /, :method => self.method(:exit_match) },
25
+ :attribute => { :re => /^(?<key>[A-Za-z0-9()\s#'-.&]+)([:|=](?<value>.*))?/, :method => self.method(:attribute_match) }
26
+ }.freeze
27
+ @command_arguments = "-adpallinfo -aall".freeze
28
+ @command_output_file = "adpallinfo_aall".freeze
29
+ end
30
+
31
+ def parse!(lsi,opts)
32
+ fake = opts[:fake].nil? ? @command_arguments : File.join(opts[:fake],@command_output_file)
33
+ super lsi, :fake => fake, :megacli => opts[:megacli]
34
+ end
35
+
36
+ # State Machine
37
+
38
+ workflow do
39
+
40
+ state :start do
41
+ event :adapter_line, :transitions_to => :adapter
42
+ event :exit_line, :transitions_to => :exit
43
+ end
44
+
45
+ state :adapter do
46
+ event :adapter_line, :transitions_to => :adapter # empty adapter
47
+ event :section_line, :transitions_to => :section
48
+ event :exit_line, :transitions_to => :exit
49
+ end
50
+
51
+ state :section do
52
+ event :exit_line, :transitions_to => :exit
53
+ event :adapter_line, :transitions_to => :adapter
54
+ event :attribute_line, :transitions_to => :attribute
55
+ end
56
+
57
+ state :attribute do
58
+ event :attribute_line, :transitions_to => :attribute
59
+ event :section_line, :transitions_to => :section
60
+ event :adapter_line, :transitions_to => :adapter
61
+ event :exit_line, :transitions_to => :exit
62
+ end
63
+
64
+ state :exit
65
+
66
+ on_transition do |from, to, triggering_event, *event_args|
67
+ #puts self.spec.states[to].class
68
+ # puts " transition: #{from} >> #{triggering_event}! >> #{to}: #{event_args.join(' ')}"
69
+ #puts " #{current_state.meta}"
70
+ end
71
+ end
72
+
73
+ ### Match Handlers
74
+
75
+ def section_match(k,match)
76
+ @log.debug "ADPINFO_SECTION! #{k} -> #{match.string}"
77
+ section_line!(LSI::Adapter::Section.new(k))
78
+ end
79
+
80
+ ### Line Handlers
81
+
82
+ def section_line(section)
83
+ @log.debug " [#{current_state}] event: section_line: new #{section.inspect}"
84
+ end
85
+
86
+ def on_section_entry(old_state, event, *args)
87
+ @log.debug " [#{current_state}] on_entry: leaving #{old_state}; args: #{args}"
88
+ unless @context.current.nil?
89
+ @context.close if Elesai::LSI::Adapter::Section === @context.current
90
+ end
91
+ @context.current.add_section(args[0])
92
+ @context.open(args[0])
93
+ end
94
+
95
+ def on_section_exit(new_state, event, *args)
96
+ @log.debug " [#{current_state}] on_exit: entering #{new_state}; args: #{args}"
97
+ @context.flash!(new_state)
98
+ end
99
+
100
+ end
101
+
102
+ end end
@@ -0,0 +1,107 @@
1
+ module Elesai; module Megacli
2
+
3
+ class AdpBbuCmd_aAll < Megacli
4
+
5
+ def initialize
6
+ @megacli = { :bbu => { :re => /^BBU status for Adapter:\s+(?<value>\d+)/, :method => self.method(:bbu_match) },
7
+ :firmwarestatus => { :re => /^BBU Firmware Status:/, :method => self.method(:section_match) },
8
+ :designinfo => { :re => /^BBU Design Info for Adapter:\s+(?<value>\d+)/, :method => self.method(:section_match) },
9
+ :properties => { :re => /^BBU Properties for Adapter:\s+(?<value>\d+)/, :method => self.method(:section_match) },
10
+ :gasgaugestatus => { :re => /^GasGuageStatus:/, :method => self.method(:section_match) },
11
+ :capacityinfo => { :re => /^BBU Capacity Info for Adapter:\s+(?<value>\d+)/, :method => self.method(:section_match) },
12
+ :exit => { :re => /^Exit Code: /, :method => self.method(:exit_match) },
13
+ :attribute => { :re => /^(?<key>[A-Za-z0-9()\s#'-.&]+)[:|=](?<value>.*)/, :method => self.method(:attribute_match) }
14
+ }.freeze
15
+ @command_arguments = "-adpbbucmd -aall".freeze
16
+ @command_output_file = "adpbbucmd_aall".freeze
17
+ end
18
+
19
+ def parse!(lsi,opts)
20
+ fake = opts[:fake].nil? ? @command_arguments : File.join(opts[:fake],@command_output_file)
21
+ super lsi, :fake => fake, :megacli => opts[:megacli]
22
+ end
23
+
24
+ # State Machine
25
+
26
+ workflow do
27
+
28
+ state :start do
29
+ event :bbu_line, :transitions_to => :bbu
30
+ event :exit_line, :transitions_to => :exit
31
+ end
32
+
33
+ state :bbu do
34
+ event :attribute_line, :transitions_to => :attribute
35
+ event :section_line, :transitions_to => :section
36
+ end
37
+
38
+ state :section do
39
+ event :exit_line, :transitions_to => :exit
40
+ event :attribute_line, :transitions_to => :attribute
41
+ end
42
+
43
+ state :attribute do
44
+ event :attribute_line, :transitions_to => :attribute
45
+ event :section_line, :transitions_to => :section
46
+ event :exit_line, :transitions_to => :exit
47
+ end
48
+
49
+ state :exit
50
+
51
+ end
52
+
53
+ # Regular Expression Match Handlers
54
+
55
+ def bbu_match(k,match)
56
+ @log.debug "BBU! #{match.string}"
57
+ key = 'id'
58
+ value = match[:value]
59
+ adapter_line(LSI::Adapter.new,key,value)
60
+ bbu_line!(LSI::BBU.new,key,value)
61
+ end
62
+
63
+ def section_match(k,match)
64
+ @log.debug "ADPINFO_SECTION! #{k} -> #{match.string}"
65
+ section_line!(LSI::BBU::Section.new(k))
66
+ end
67
+
68
+ ### Line Handlers
69
+
70
+ def bbu_line(bbu,key,value)
71
+ @log.debug " [#{current_state}] event: bbu_line: new #{bbu.inspect}"
72
+ bbu[key.to_sym] = value.to_i
73
+ end
74
+
75
+ def on_bbu_entry(old_state, event, *args)
76
+ @log.debug " [#{current_state}] on_entry: leaving #{old_state}; args: #{args}"
77
+ @context.open args[0]
78
+ end
79
+
80
+ def on_bbu_exit(new_state, event, *args)
81
+ @log.debug " [#{current_state}] on_exit: entering #{new_state}; args: #{args}"
82
+ @context.flash!(new_state)
83
+ end
84
+
85
+ def section_line(section)
86
+ @log.debug " [#{current_state}] event: section_line: new #{section.inspect}"
87
+ end
88
+
89
+ def on_section_entry(old_state, event, *args)
90
+ @log.debug " [#{current_state}] on_entry: leaving #{old_state}; args: #{args}"
91
+ unless @context.current.nil?
92
+ @context.close if Elesai::LSI::BBU::Section === @context.current
93
+ end
94
+ @context.current.add_section(args[0])
95
+ @context.open(args[0])
96
+ end
97
+
98
+ def on_section_exit(new_state, event, *args)
99
+ @log.debug " [#{current_state}] on_exit: entering #{new_state}; args: #{args}"
100
+ @context.flash!(new_state)
101
+ end
102
+
103
+ end
104
+
105
+ end end
106
+
107
+
@@ -0,0 +1,140 @@
1
+ module Elesai; module Megacli
2
+
3
+ class LDPDinfo_aAll < Megacli
4
+
5
+ def initialize
6
+ @megacli = { :adapter => { :re => /^Adapter\s+#*(?<value>\d+)/, :method => self.method(:adapter_match) },
7
+ :virtualdrive => { :re => /^Virtual\s+Drive:\s+\d+\s+\((?<key>Target\s+Id):\s+(?<value>\d+)\)/, :method => self.method(:virtualdrive_match) },
8
+ :physicaldrive => { :re => /^(?<key>Enclosure\s+Device\s+ID):\s+(?<value>\d+)/, :method => self.method(:physicaldrive_match) },
9
+ :exit => { :re => /^Exit Code: /, :method => self.method(:exit_match) },
10
+ :attribute => { :re => /^(?<key>[A-Za-z0-9()\s#'-.&]+)[:|=](?<value>.*)/, :method => self.method(:attribute_match) }
11
+ }.freeze
12
+ @command_arguments = "-ldpdinfo -aall".freeze
13
+ @command_output_file = "ldpdinfo_aall".freeze
14
+ end
15
+
16
+ def parse!(lsi,opts)
17
+ fake = opts[:fake].nil? ? @command_arguments : File.join(opts[:fake],@command_output_file)
18
+ super lsi, :fake => fake, :megacli => opts[:megacli]
19
+ end
20
+
21
+ # Regular Expression Match Handlers
22
+
23
+ def virtualdrive_match(k,match)
24
+ @log.debug "VIRTUALDRIVE! #{match.string}"
25
+ key = match[:key].gsub(/\s+/,"").downcase
26
+ value = match[:value]
27
+ virtualdrive_line!(LSI::VirtualDrive.new,key,value)
28
+ end
29
+
30
+ def physicaldrive_match(k,match)
31
+ @log.debug "PHYSICALDRIVE! #{match.string}"
32
+ key = match[:key].gsub(/\s+/,"").downcase
33
+ value = match[:value]
34
+ physicaldrive_line!(LSI::PhysicalDrive.new,key,value)
35
+ end
36
+
37
+ # Line Handlers
38
+
39
+ def adapter_line(adapter,key,value)
40
+ @log.debug " [#{current_state}] event adapter_line: new #{adapter.inspect}"
41
+ adapter[key.to_sym] = value.to_i
42
+ end
43
+
44
+ def on_adapter_entry(old_state, event, *args)
45
+ @log.debug " [#{current_state}] on_entry: leaving #{old_state}; args: #{args}"
46
+
47
+ @context.close unless @context.current.nil? or Elesai::LSI::Adapter === @context.current
48
+ @context.open args[0]
49
+ end
50
+
51
+ def on_adapter_exit(new_state, event, *args)
52
+ @log.debug " [#{current_state}] on_exit: entering #{new_state}; args: #{args}"
53
+ @context.flash!(new_state)
54
+ end
55
+
56
+ def virtualdrive_line(virtualdrive,key,value)
57
+ @log.debug " [#{current_state}] event: virtualdrive_line: new #{virtualdrive.inspect}"
58
+ virtualdrive[key.to_sym] = value.to_i
59
+ end
60
+
61
+ def on_virtualdrive_entry(old_state, event, *args)
62
+ @log.debug " [#{current_state}] on_entry: leaving #{old_state}; args: #{args}"
63
+
64
+ unless @context.current.nil?
65
+ if Elesai::LSI::VirtualDrive === @context.current
66
+ @context.close
67
+ end
68
+ end
69
+ virtualdrive = args[0]
70
+ @context.open virtualdrive
71
+ end
72
+
73
+ def on_virtualdrive_exit(new_state, event, *args)
74
+ @log.debug " [#{current_state}] on_exit: entering #{new_state}; args: #{args}"
75
+ @context.flash!(new_state)
76
+ end
77
+
78
+ # Physical Drive
79
+
80
+ def physicaldrive_line(physicaldrive,key,value)
81
+ @log.debug " [#{current_state}] event: physicaldrive_line: new #{physicaldrive.inspect}"
82
+ physicaldrive[key.to_sym] = value.to_i
83
+ end
84
+
85
+ def on_physicaldrive_entry(old_state, event, *args)
86
+ @log.debug " [#{current_state}] on_entry: leaving #{old_state}; args: #{args}"
87
+ @context.open args[0]
88
+ end
89
+
90
+ def on_physicaldrive_exit(new_state, event, *args)
91
+ @log.debug " [#{current_state}] on_exit: entering #{new_state}; args: #{args}"
92
+ @context.flash!(new_state)
93
+ end
94
+
95
+ workflow do
96
+
97
+ state :start do
98
+ event :adapter_line, :transitions_to => :adapter
99
+ event :exit_line, :transitions_to => :exit
100
+ end
101
+
102
+ state :adapter do
103
+ event :adapter_line, :transitions_to => :adapter
104
+ event :attribute_line, :transitions_to => :attribute
105
+ event :virtualdrive_line, :transitions_to => :virtualdrive
106
+ event :exit_line, :transitions_to => :exit
107
+ end
108
+
109
+ state :physicaldrive do
110
+ event :attribute_line, :transitions_to => :physicaldrive
111
+ event :exit_line, :transitions_to => :exit
112
+ event :adapter_line, :transitions_to => :adapter
113
+ event :physicaldrive_line, :transitions_to => :physicaldrive
114
+ event :attribute_line, :transitions_to => :attribute
115
+ end
116
+
117
+ state :virtualdrive do
118
+ event :physicaldrive_line, :transitions_to => :physicaldrive
119
+ event :attribute_line, :transitions_to => :attribute
120
+ end
121
+
122
+ state :attribute do
123
+ event :attribute_line, :transitions_to => :attribute
124
+ event :virtualdrive_line, :transitions_to => :virtualdrive
125
+ event :physicaldrive_line, :transitions_to => :physicaldrive
126
+ event :adapter_line, :transitions_to => :adapter
127
+ event :exit_line, :transitions_to => :exit
128
+ end
129
+
130
+ state :exit
131
+
132
+ on_transition do |from, to, triggering_event, *event_args|
133
+ #puts self.spec.states[to].class
134
+ # puts " transition: #{from} >> #{triggering_event}! >> #{to}: #{event_args.join(' ')}"
135
+ #puts " #{current_state.meta}"
136
+ end
137
+ end
138
+
139
+ end
140
+ end; end