Class: Aio::Device::ParentDevice

Inherits:
Object
  • Object
show all
Includes:
Ui::Verbose
Defined in:
lib/aio/core/device/parent_device.rb

Direct Known Subclasses

Cisco, H3C, Huawei, Juniper, Maipu

Constant Summary collapse

InvalidInput =

设备类型attr_reader :device_type

/Invalid input detected/
Interface =
{
  geth:     "GigabitEthernet",
  feth:     "FastEthernet",
  eth:      "Ethernet",
  loopback: "Loopback",
  vlan_if:  "Vlan-interface"
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Ui::Verbose

#clear_line, #print_error, #print_good, #progress_bar

Constructor Details

#initializeParentDevice

Returns a new instance of ParentDevice.



47
48
49
50
51
52
53
54
55
# File 'lib/aio/core/device/parent_device.rb', line 47

def initialize
  self.cmds_context = {}
  self.device_name = ""
  self.cmds_useful = {}

  @warning_klass = Aio::Text::Warning.new
  @device_type = ""
  @device_info = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &block) ⇒ Object

1.导向命令方法模块2.导向Warning类



235
236
237
238
239
240
241
242
243
244
245
# File 'lib/aio/core/device/parent_device.rb', line 235

def method_missing(m, *args, &block)
  if Aio::Device::Methods.respond_to?(m)
    Aio::Device::Methods.klass = self
    Aio::Device::Methods.send(m)

  elsif Aio::Text::Warning.instance_methods(false).include?(m.to_sym)
    warning_klass.send(m, *args)
  else
    super
  end
end

Instance Attribute Details

#cmds_contextObject

cmds_context = { “cmd_full_name” => [ { device_type_1 => klass1, device_type_2 => klass2}, context ] }



14
15
16
# File 'lib/aio/core/device/parent_device.rb', line 14

def cmds_context
  @cmds_context
end

#cmds_usefulObject

按cmd名称管理有用信息Hash = { cmd_name => { :case => useful } }



24
25
26
# File 'lib/aio/core/device/parent_device.rb', line 24

def cmds_useful
  @cmds_useful
end

#device_infoObject

设备的基本信息



20
21
22
# File 'lib/aio/core/device/parent_device.rb', line 20

def device_info
  @device_info
end

#device_nameObject Also known as: name

Returns the value of attribute device_name.



8
9
10
# File 'lib/aio/core/device/parent_device.rb', line 8

def device_name
  @device_name
end

#manager_ipObject

管理IP



17
18
19
# File 'lib/aio/core/device/parent_device.rb', line 17

def manager_ip
  @manager_ip
end

#warning_klassObject

Warning信息模块



27
28
29
# File 'lib/aio/core/device/parent_device.rb', line 27

def warning_klass
  @warning_klass
end

Instance Method Details

#add_cmd(klass_info) ⇒ Object

增加cmd



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/aio/core/device/parent_device.rb', line 81

def add_cmd(klass_info)
  maybe_device_type = klass_info[0]
  cmd_klass = klass_info[1]

  cmd_full_name = cmd_klass.cmd_full

  # 有可能已经有了其他设备类型的模块
  # 那么通过Hash的方式存储所有的模块
  cmds_context[cmd_full_name] ||= []
  cmds_context[cmd_full_name][0] ||= {}
  cmds_context[cmd_full_name][0][maybe_device_type] = cmd_klass
  return cmd_full_name
end

#add_cmd_context_by_cmd_name(cmd_full_name, context) ⇒ Object

两种用法:在有klass的时候可以添加为完整cmds_context 当没有klass的话,也可以加。那么klass项为nil



98
99
100
101
# File 'lib/aio/core/device/parent_device.rb', line 98

def add_cmd_context_by_cmd_name(cmd_full_name, context)
  cmds_context[cmd_full_name] ||= []
  cmds_context[cmd_full_name][1] = context
end

#add_cmd_context_by_klass(klass_info, context) ⇒ Object

整合上面两个方法,成为一步



104
105
106
107
108
# File 'lib/aio/core/device/parent_device.rb', line 104

def add_cmd_context_by_klass(klass_info, context)
  cmd_full_name = add_cmd(klass_info)
  add_cmd_context_by_cmd_name(cmd_full_name, context)
  return cmds_context[cmd_full_name]
end

#device_typeObject



65
66
67
68
69
70
71
# File 'lib/aio/core/device/parent_device.rb', line 65

def device_type
  if @device_type.empty?
    return "other"
  end

  @device_type
end

#has_cmd?(cmd) ⇒ Boolean

判断是否有cmd的信息

Returns:

  • (Boolean)


74
75
76
# File 'lib/aio/core/device/parent_device.rb', line 74

def has_cmd?(cmd)
  @cmds_useful.has_key?(cmd)
end

#inspectObject



61
62
63
# File 'lib/aio/core/device/parent_device.rb', line 61

def inspect
  "#<#{self.class}>"
end

#instanceObject



57
58
59
# File 'lib/aio/core/device/parent_device.rb', line 57

def instance
  self
end

#interfaceObject

FIXME 无法获得正确的父类Interface



43
44
45
# File 'lib/aio/core/device/parent_device.rb', line 43

def interface
  self.class::Interface
end

#parseObject

最终解析的地方一定要确定设备类型,否则的话只能单一设备cmds_context = { cmd_name => [ { device_type_1 => klass1, device_type_2 => klass2}, context ] }



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/aio/core/device/parent_device.rb', line 116

def parse

  # 做两次循环,第一次确定设备类型
  2.times do |t|
    cmds_context.each_pair do |cmd_name, info|
      context = info[1]

      # 如果没有cmd模块, 那么就跳过
      next if info[0].nil?

      info[0].each_pair do |device_type, module_klass|

        #module_klass.clear_useful

        # 如果找到了设备类型
        # 那么之后就只对该类型进行解析,其他的跳过
        if ! @device_type.empty? and @device_type != device_type
          next
        end

        module_klass.context = context
        module_klass.warning_klass = @warning_klass

        # 循环模块对内容进行解析
        # 当是第一遍遍历的时候,只找可以决定是什么设备类型的命令
        # 一般都是通过show version 这类命令找到, 那么同时也能找到设备型号和软件版本
        if t == 0 and not module_klass.key_stand
          next

        elsif t == 0 and module_klass.key_stand
          module_klass.parse
          push_device_info(module_klass)

          module_klass.clear_useful
          # 当device_type 有内容时,确定为已知设备类型,那么进行下次循环遍历
          if @device_type.empty?
            next
          else
            @warning_klass.clear
            break
          end
        end

        begin
          # 当是第二遍的时候,则全部解析
          module_klass.clear_useful
          module_klass.device_info = device_info
          module_klass.ext_info = {:device_name => @device_name}
          module_klass.parse
        rescue Aio::Text::Context::OutLineError
        rescue NoMethodError
          print_error "未找到方法,请检查模块的方法名拼写"
        rescue NameError
          print_error "#{module_klass.class} 未检测到对应版本"
        rescue Exception => e
          print_error "#{e.class} : #{module_klass.class}"
          print_error e.message
        ensure
          push_useful(module_klass, cmd_name)
          next
        end
      end
    end
  end

  # 当所有解析循环完成后,如果找到了设备类型
  # 就将此类转为对应子类
  # changeto
  if ! @device_type.empty?
    to = self.send("changeto_#{@device_type}")
  end

  return to ? to : self
end

#push_device_info(module_klass) ⇒ Object

存放设备基本信息



192
193
194
195
196
197
# File 'lib/aio/core/device/parent_device.rb', line 192

def push_device_info(module_klass)
  @device_type = module_klass.useful[:device_type].to_s
  @device_info[:device_model] = module_klass.useful[:device_model].to_s
  @device_info[:device_version] = module_klass.useful[:device_version].to_s
  @device_info[:device_template] = module_klass.useful[:device_template].to_s
end

#push_useful(module_klass, cmd_name) ⇒ Object

当一个模块解析完毕后,将有用信息放入cmds_useful 当有用信息中device_type类为真时,就可以将此父类转变为具体的类型了check



203
204
205
206
207
208
209
210
211
212
# File 'lib/aio/core/device/parent_device.rb', line 203

def push_useful(module_klass, cmd_name)

  if Aio::Base::Debug.enable?
    puts "parent_device#push_useful"
    pp module_klass
  end

  # 将有用信息放入整体有用信息
  cmds_useful[cmd_name] = module_klass.useful 
end