construqt 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/construqt/addresses.rb +121 -10
  3. data/lib/construqt/bgps.rb +10 -12
  4. data/lib/construqt/firewalls.rb +115 -16
  5. data/lib/construqt/flavour/ciscian/ciscian.rb +73 -93
  6. data/lib/construqt/flavour/ciscian/deploy_template.rb +36 -0
  7. data/lib/construqt/flavour/ciscian/dialect_dlink-dgs15xx.rb +62 -114
  8. data/lib/construqt/flavour/ciscian/dialect_hp-2510g.rb +74 -14
  9. data/lib/construqt/flavour/delegates.rb +9 -0
  10. data/lib/construqt/flavour/mikrotik/flavour_mikrotik.rb +0 -3
  11. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_bgp.rb +12 -1
  12. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_interface.rb +32 -1
  13. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_result.rb +2 -0
  14. data/lib/construqt/flavour/mikrotik/flavour_mikrotik_schema.rb +3 -3
  15. data/lib/construqt/flavour/plantuml/plantuml.rb +2 -2
  16. data/lib/construqt/flavour/ubuntu/flavour_ubuntu.rb +24 -13
  17. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_bgp.rb +16 -7
  18. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_dns.rb +5 -5
  19. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb +218 -67
  20. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_ipsec.rb +33 -17
  21. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_opvn.rb +5 -5
  22. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_result.rb +77 -14
  23. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_services.rb +77 -29
  24. data/lib/construqt/flavour/ubuntu/flavour_ubuntu_vrrp.rb +18 -3
  25. data/lib/construqt/interfaces.rb +25 -6
  26. data/lib/construqt/ipsecs.rb +5 -3
  27. data/lib/construqt/rack.rb +51 -0
  28. data/lib/construqt/resource.rb +25 -3
  29. data/lib/construqt/reverse.rb +1 -0
  30. data/lib/construqt/services.rb +15 -29
  31. data/lib/construqt/tags.rb +21 -15
  32. data/lib/construqt/templates.rb +17 -0
  33. data/lib/construqt/users.rb +4 -0
  34. data/lib/construqt/util.rb +1 -1
  35. data/lib/construqt/version.rb +1 -1
  36. data/lib/construqt/vlans.rb +13 -2
  37. data/lib/construqt.rb +2 -1
  38. metadata +4 -2
@@ -1,3 +1,5 @@
1
+ require_relative("deploy_template")
2
+
1
3
  module Construqt
2
4
  module Flavour
3
5
  module Ciscian
@@ -34,21 +36,6 @@ module Construqt
34
36
  @to_s = str
35
37
  @nr = nr
36
38
  end
37
-
38
- def <=>(other)
39
- a = self.to_s
40
- b = other.to_s
41
- match_a=/^(.*[^\d])(\d+)$/.match(a)||[nil,a,1]
42
- match_b=/^(.*[^\d])(\d+)$/.match(b)||[nil,b,1]
43
- #puts match_a, match_b, a, b
44
- ret = match_a[1]<=>match_b[1]
45
- ret = match_a[2].to_i<=>match_b[2].to_i if ret==0
46
- ret
47
- end
48
-
49
- # def hash
50
- # self.to_s.hash
51
- # end
52
39
  end
53
40
 
54
41
  def initialize(lines)
@@ -91,19 +78,25 @@ module Construqt
91
78
  end
92
79
  end
93
80
 
94
- def commit
95
- self.dialect.commit
96
-
81
+ def serialize
97
82
  block=[]
98
- @sections.keys.sort.each do |key|
83
+ section_keys = self.dialect.sort_section_keys(@sections.keys)
84
+ section_keys.each do |key|
99
85
  section = @sections[key]
100
86
  block += section.serialize
101
87
  end
88
+ block
89
+ end
102
90
 
103
- Util.write_str(block.join("\n"), File.join(@host.name, "#{@host.fname||self.dialect.class.name}.cfg"))
91
+ def commit
92
+ self.dialect.commit
93
+ Util.write_str(self.serialize().join("\n"), File.join(@host.name, "#{@host.fname||self.dialect.class.name}.cfg"))
94
+ external=@host.id.interfaces.first.address
95
+ external_ip=external.first_ipv4.nil? ? external.first_ipv6.to_s : external.first_ipv4.to_s
96
+ DeployTemplate.write_template(@host, self.dialect.class.name, external_ip, "root", @host.password||@host.region.hosts.default_password)
104
97
  end
105
98
 
106
- def add(section, clazz=NestedSection)
99
+ def add(section, clazz=SingleValueVerb)
107
100
  throw "section is nil" unless section
108
101
  section = Lines::Line.new(section, -1) unless section.kind_of?(Lines::Line)
109
102
  section_key=Result.normalize_section_key(section.to_s)
@@ -115,7 +108,7 @@ module Construqt
115
108
  @sections[section_key].yes
116
109
  end
117
110
 
118
- yield(@sections[section_key]) if block_given?
111
+ yield(@sections[section_key]) if block_given?
119
112
  @sections[section_key]
120
113
  end
121
114
 
@@ -129,7 +122,7 @@ module Construqt
129
122
 
130
123
  deltas=NestedSection.compare(nu_root, other_root)
131
124
  throw "illegal state" if deltas.length != 1
132
- result.sections = deltas[0]
125
+ result.sections = deltas[0].sections unless deltas[0].nil?
133
126
  result
134
127
  end
135
128
  end
@@ -141,18 +134,21 @@ module Construqt
141
134
  end
142
135
 
143
136
  def serialize
144
- [[@no, section , value].compact.join(" ")]
137
+ val = @quotes ? "\"#{value}\"" : value
138
+ [[@no, section , val].compact.join(" ")]
145
139
  end
146
140
 
147
141
  def self.compare(nu, old)
148
142
  return [nu] unless old
149
- return [old.no] unless nu
143
+ # return no changes (empty list) if old configuration of single value verb (default) is not explicitly reconfigured in new configuration:
144
+ return [] unless nu
150
145
  return [nu] unless nu.serialize == old.serialize
151
146
  [nil]
152
147
  end
153
148
 
154
149
  def add(value)
155
150
  self.value=value
151
+ self
156
152
  end
157
153
 
158
154
  def no
@@ -166,10 +162,19 @@ module Construqt
166
162
  self
167
163
  end
168
164
 
165
+ def quotes
166
+ @quotes=true
167
+ self
168
+ end
169
+
169
170
  def self.parse_line(line, lines, section, result)
170
- regexp = line.to_s.strip.end_with?("\"") ? /^(.*) (\"[^"]+\")$/ : /^(.*) ([^\s"]+)$/
171
+ quotes = line.to_s.strip.end_with?("\"")
172
+ regexp = quotes ? /^\s*((no|).*) \"([^"]+)\"$/ : /^\s*((no|).*) ([^\s"]+)$/
171
173
  if (line.to_s.strip =~ regexp)
172
- section.add($1, Ciscian::SingleValueVerb).add($2)
174
+ key=$1
175
+ val=$3
176
+ sec = section.add(key, Ciscian::SingleValueVerb).add(val)
177
+ sec.quotes if quotes
173
178
  else
174
179
  section.add(line.to_s, Ciscian::SingleValueVerb)
175
180
  end
@@ -183,20 +188,21 @@ module Construqt
183
188
  self.section=section
184
189
  end
185
190
 
186
- def add(verb, clazz = MultiValueVerb)
187
- # if verb.respond_to?(:section_key)
188
- # clazz=verb
189
- # verb=clazz.section_key
190
- # end
191
+ def add(verb, clazz = SingleValueVerb)
192
+ section_key=Result.normalize_section_key(verb.to_s)
193
+ self.sections[section_key] ||= clazz.new(section_key)
191
194
 
192
- self.sections[Result.normalize_section_key(verb.to_s)] ||= clazz.new(verb)
195
+ if Result.starts_with_no(verb.to_s)
196
+ @sections[section_key].no
197
+ end
198
+ @sections[section_key]
193
199
  end
194
200
 
195
201
  def self.parse_line(line, lines, section, result)
196
- #binding.pry if line.start_with?("interface")
197
202
  if [/^\s*(no\s+|)interface/, /^\s*(no\s+|)vlan/].find{|i| line.to_s.match(i) }
198
203
  resultline=Result::Lines::Line.new(result.dialect.clear_interface(line), line.nr)
199
- section.add(resultline.to_s) do |_section|
204
+ section.add(resultline.to_s, NestedSection) do |_section|
205
+ _section.virtual if result.dialect.is_virtual?(resultline.to_s)
200
206
  while _line = lines.shift
201
207
  break if result.dialect.block_end?(_line.to_s)
202
208
  result.parse_line(_line, lines, _section, result)
@@ -208,7 +214,7 @@ module Construqt
208
214
  if (ports.length>1)
209
215
  section_to_split=section.sections.delete(resultline.to_s)
210
216
  ports.each do |port|
211
- section.add(line.to_s.gsub(/#{Construqt::Util::PORTS_DEF_REGEXP}/, port)) do |_section|
217
+ section.add(line.to_s.gsub(/#{Construqt::Util::PORTS_DEF_REGEXP}/, port), NestedSection) do |_section|
212
218
  _section.sections.merge!(section_to_split.sections)
213
219
  end
214
220
  end
@@ -244,12 +250,19 @@ module Construqt
244
250
  self
245
251
  end
246
252
 
253
+ def virtual
254
+ @virtual=true
255
+ self
256
+ end
257
+
247
258
  def serialize
248
259
  block=[]
249
- block << "#{@no}#{section.to_s}"
250
- unless (@no)
251
- block += render_verbs(self.sections)
252
- block << "exit"
260
+ if (!self.sections.empty? || (self.sections.empty? && @virtual) || (@no && @virtual))
261
+ block << "#{@no}#{section.to_s}"
262
+ unless (@no)
263
+ block += render_verbs(self.sections)
264
+ block << "exit"
265
+ end
253
266
  end
254
267
 
255
268
  block
@@ -259,6 +272,7 @@ module Construqt
259
272
  return [nu] unless old
260
273
  return [old.no] unless nu
261
274
  throw "classes must match #{nu.class.name} != #{old.class.name}" unless nu.class == old.class
275
+
262
276
  if (nu.serialize==old.serialize)
263
277
  return [nil]
264
278
  else
@@ -266,7 +280,7 @@ module Construqt
266
280
  return [nu]
267
281
  else
268
282
  delta = nu.class.new(nu.section)
269
- (nu.sections.keys + old.sections.keys).sort.each do |k,v|
283
+ (nu.sections.keys + old.sections.keys).uniq.sort.each do |k,v|
270
284
  nu_section=nu.sections[k]
271
285
  old_section=old.sections[k]
272
286
  comps = (nu_section||old_section).class.compare(nu_section, old_section)
@@ -282,48 +296,6 @@ module Construqt
282
296
  end
283
297
  end
284
298
 
285
- class MultiValueVerb
286
- attr_accessor :section,:values
287
- def initialize(section)
288
- self.section=section
289
- self.values = []
290
- end
291
-
292
- def add(value)
293
- self.values << value
294
- self
295
- end
296
-
297
- def no
298
- @no="no "
299
- self
300
- end
301
-
302
- def yes
303
- @no=nil
304
- self
305
- end
306
-
307
- def serialize
308
- if @no
309
- ["#{@no}#{section}"]
310
- else
311
- ["#{section} #{values.join(",")}"]
312
- end
313
- end
314
-
315
- def self.compare(nu, old)
316
- return [nu] unless old
317
- return [old.no] unless nu
318
- throw "classes must match #{nu.class.name} != #{old.class.name}" unless nu.class == old.class
319
- if (nu.serialize==old.serialize)
320
- [nil]
321
- else
322
- [nu]
323
- end
324
- end
325
- end
326
-
327
299
  class RangeVerb
328
300
  attr_accessor :section,:values
329
301
  def initialize(section)
@@ -360,7 +332,7 @@ module Construqt
360
332
 
361
333
  def serialize
362
334
  if @no
363
- ["#{@no}#{section}"]
335
+ ["#{@no}#{section} #{Construqt::Util.createRangeDefinition(values)}"]
364
336
  else
365
337
  ["#{section} #{Construqt::Util.createRangeDefinition(values)}"]
366
338
  end
@@ -449,6 +421,12 @@ module Construqt
449
421
  end
450
422
 
451
423
  def self.compare(nu, old)
424
+ unless (nu.nil? || old.nil?)
425
+ if (nu.serialize==old.serialize)
426
+ return []
427
+ end
428
+ end
429
+
452
430
  nu_ports=nu.nil? ? {} : nu.integrate
453
431
  old_ports=old.nil? ? {} : old.integrate
454
432
 
@@ -561,6 +539,10 @@ module Construqt
561
539
  return sets
562
540
  end
563
541
 
542
+ def always_select_empty_pattern
543
+ false
544
+ end
545
+
564
546
  def determine_output_patterns(value_sets)
565
547
  output_patterns=[]
566
548
  empty_pattern = nil
@@ -578,20 +560,18 @@ module Construqt
578
560
  end
579
561
  end
580
562
 
581
- output_patterns << empty_pattern if output_patterns.empty? && !empty_pattern.nil?
563
+ output_patterns.unshift(empty_pattern) if (output_patterns.empty? || self.always_select_empty_pattern) && !empty_pattern.nil?
582
564
  return output_patterns
583
565
  end
584
566
 
567
+ def group?
568
+ true
569
+ end
570
+
585
571
  def serialize
586
572
  buffer = []
587
573
  sets = integrate
588
574
 
589
- # deactivate grouping, if one variable has a custom regex (i.e. is not a range definition)
590
- group=true
591
- self.class.variables(self.class.patterns).each do |v|
592
- group=false unless self.class.find_regex(self.class.extract_varname(v)).nil?
593
- end
594
-
595
575
  sets.each do |key_val,value_sets|
596
576
  determine_output_patterns(value_sets).each do |pattern|
597
577
  index = 0
@@ -601,8 +581,8 @@ module Construqt
601
581
  result = pattern
602
582
  i += 1
603
583
  self.class.find_variables(pattern).each do |v|
604
- if (group)
605
- if self.class.is_value?(v) || self.class.is_key_value?(v)
584
+ if (self.group?)
585
+ if (!value_sets[v].kind_of?(Array) && (self.class.is_value?(v) || self.class.is_key_value?(v)))
606
586
  result = result.gsub(v, value_sets[v].to_s) unless value_sets[v].nil? || value_sets[v].to_s.empty?
607
587
  else
608
588
  result = result.gsub(v, Construqt::Util.createRangeDefinition(value_sets[v])) unless value_sets[v].nil? || value_sets[v].empty?
@@ -0,0 +1,36 @@
1
+ module Construqt
2
+ module Flavour
3
+ module Ciscian
4
+ class DeployTemplate
5
+ def self.write_template(host, flavour, ip, user, pass)
6
+ template = <<-TEMPLATE
7
+ #!/bin/bash
8
+
9
+ CURRENT_DIR="`pwd`/$(dirname $0)"
10
+ if [[ ! -e $CURRENT_DIR ]]
11
+ then
12
+ CURRENT_DIR="$(dirname $0)"
13
+ fi
14
+
15
+ if [ -z "$CONSTRUQT_PATH" ]
16
+ then
17
+ if [[ $CURRENT_DIR =~ (.*construqt).* ]]
18
+ then
19
+ CONSTRUQT_PATH=${BASH_REMATCH[1]}
20
+ else
21
+ echo "could not automatically find construqt path"
22
+ exit
23
+ fi
24
+ fi
25
+
26
+ FLAVOUR="#{flavour}"
27
+ cd $CONSTRUQT_PATH
28
+ bash $CONSTRUQT_PATH/construqt/switch/deploy/deploy.sh $FLAVOUR #{ip} #{user} #{pass} "$CURRENT_DIR/$FLAVOUR.cfg"
29
+ cd - > /dev/null
30
+ TEMPLATE
31
+ Util.write_str(template, File.join(host.name, "deploy.sh"))
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -52,6 +52,10 @@ module Construqt
52
52
  "channel-group"
53
53
  end
54
54
 
55
+ def always_select_empty_pattern
56
+ true
57
+ end
58
+
55
59
  def self.patterns
56
60
  ["no channel-group", "channel-group {+channel} mode active"]
57
61
  end
@@ -94,12 +98,15 @@ module Construqt
94
98
  end
95
99
  end
96
100
 
97
-
98
101
  class Ipv4RouteVerb < PatternBasedVerb
99
102
  def self.section
100
103
  "ip route"
101
104
  end
102
105
 
106
+ def group?
107
+ false
108
+ end
109
+
103
110
  def self.find_regex(variable)
104
111
  {
105
112
  "routedefs" => "(\\S+\\s+\\S+\\s+\\S+)"
@@ -111,6 +118,16 @@ module Construqt
111
118
  end
112
119
  end
113
120
 
121
+ class IpHttpServerVerb < SingleValueVerb
122
+ def self.parse_line(line, lines, section, result)
123
+ regexp = /^\s*((no|) ip http server)$/
124
+ if (line.to_s.strip =~ regexp)
125
+ section.add(line.to_s, Ciscian::SingleValueVerb)
126
+ return true
127
+ end
128
+ end
129
+ end
130
+
114
131
  class Comment
115
132
  def self.parse_line(line, lines, section, result)
116
133
  line.to_s.empty? || line.to_s.start_with?("#")
@@ -126,7 +143,7 @@ module Construqt
126
143
  class Line
127
144
  def self.parse_line(line, lines, section, result)
128
145
  return false unless ['line '].find{|i| line.to_s.start_with?(i) }
129
- section.add(line) do |_section|
146
+ section.add(line, NestedSection) do |_section|
130
147
  while line = lines.shift
131
148
  break if result.dialect.block_end?(line.to_s)
132
149
  result.parse_line(line, lines, _section, result)
@@ -163,15 +180,6 @@ module Construqt
163
180
  def add_host(host)
164
181
  end
165
182
 
166
- def add_device(device)
167
- @result.add("interface #{expand_device_name(device)}") do |section|
168
- section.add("flowcontrol").add("off")
169
- section.add("max-rcv-frame-size").add(device.delegate.mtu)
170
- section.add("snmp trap").add("link-status")
171
- section.add("switchport mode").add("trunk")
172
- end
173
- end
174
-
175
183
  def clear_interface(line)
176
184
  line.to_s.split(/\s+/).map do |i|
177
185
  split = /^([^0-9]+)([0-9].*)$/.match(i)
@@ -179,6 +187,10 @@ module Construqt
179
187
  end.flatten.join(' ')
180
188
  end
181
189
 
190
+ def is_virtual?(line)
191
+ line.start_with?("vlan") || line.include?("port-channel")
192
+ end
193
+
182
194
  def parse_line(line, lines, section, result)
183
195
  [
184
196
  WtfEnd,
@@ -189,12 +201,34 @@ module Construqt
189
201
  MtuVerb,
190
202
  SwitchPortTrunkAllowedVlan,
191
203
  ChannelGroupVerb,
192
- Ipv4RouteVerb
204
+ Ipv4RouteVerb,
205
+ IpHttpServerVerb
193
206
  ].find do |i|
194
207
  i.parse_line(line, lines, section, result)
195
208
  end
196
209
  end
197
210
 
211
+ def sort_section_keys(keys)
212
+ return keys.sort do |a,b|
213
+ a = a.to_s
214
+ b = b.to_s
215
+ match_a=/^(.*[^\d])(\d+)$/.match(a)||[nil,a,1]
216
+ match_b=/^(.*[^\d])(\d+)$/.match(b)||[nil,b,1]
217
+ #puts match_a, match_b, a, b
218
+ ret=0
219
+ ret = rate_higher("vlan", match_a[1], match_b[1]) if ret==0
220
+ ret = rate_higher("interface port-channel", match_a[1], match_b[1]) if ret==0
221
+ ret = rate_higher("interface vlan", match_a[1], match_b[1]) if ret==0
222
+ ret = match_a[1]<=>match_b[1] if ret==0
223
+ ret = match_a[2].to_i<=>match_b[2].to_i if ret==0
224
+ ret
225
+ end
226
+ end
227
+
228
+ def rate_higher(prefix, a, b)
229
+ return a.start_with?(prefix) ^ b.start_with?(prefix) ? (a.start_with?(prefix) ? -1 : 1) : 0
230
+ end
231
+
198
232
  def expand_device_name(device)
199
233
  return device.delegate.dev_name if device.delegate.dev_name
200
234
  pattern = (({
@@ -217,137 +251,51 @@ module Construqt
217
251
  @result.add(verb, Ciscian::SingleValueVerb)
218
252
  end
219
253
 
220
- ["line console", "line telnet", "line ssh"].each do |section|
221
- @result.add(section) { |_section| _section.add("line") }
222
- end
223
-
224
- #@result.host.interfaces.values.each do |iface|
225
- # @result.add(k
226
- #end
227
-
228
-
229
-
230
-
231
- # "enable password level 15 7 <>"
232
- # "username root password 7 <>"
233
- # "username root password 15"
234
- #
235
- # "autoconfig",
236
- # ["clock timezone", "+ 1"],
237
- # "no clock summer-time"
238
- # "sntp interval 720"
239
- # "ddp report-timer 30",
240
- # "debug"
241
- # "debug reboot"
242
- # "dim"
243
- # "ignore"
244
- # "instance 16 vlans"
245
- # no power-saving link-detection
246
- # no dim led
247
- # no power-saving hibernation
248
- # no power-saving dim-led
249
- # no power-saving port-shutdown
250
- #
251
- #
252
- # "ddp"
253
- # "no power-saving eee"
254
- # "no snmp-server trap-sending"
255
- # "no speed"
256
- # "spanning-tree guard"
257
- # "spanning-tree mst hello-time"
258
- #
259
- #
260
- # "ip arp gratuitous"
261
- # "ip dhcp relay information option format circuit-id default"
262
- # "ip dhcp relay information option format remote-id default"
263
- # "ip dhcp relay information policy replace"
264
- # "ip domain"
265
- # "ip http service-port"
266
- # "ip http timeout-policy idle"
267
- # "ip ssh"
268
- # "ip telnet"
269
- # "ip telnet service-port"
270
- # "port-channel load-balance"
271
- # "power-saving"
272
- # "service"
273
- #
274
- # "snmp-server community private view CommunityView"
275
- # "snmp-server community public view CommunityView"
276
- # "snmp-server contact"
277
- # "snmp-server enable traps rmon falling-alarm"
278
- # "snmp-server enable traps snmp rising-alarm"
279
- # "snmp-server engineID local"
280
- # "snmp-server group initial"
281
- # "snmp-server group initial v3 noauth read restricted notify"
282
- # "snmp-server group private v1 read CommunityView write CommunityView notify"
283
- # "snmp-server group private v2c read CommunityView write CommunityView notify"
284
- # "snmp-server group public v1 read CommunityView notify"
285
- # "snmp-server group public v2c read CommunityView notify"
286
- # "snmp-server location"
287
- # "snmp-server response"
288
- # "snmp-server service-port"
289
- # "snmp-server user initial"
290
- # "snmp-server user initial initial"
291
- # "snmp-server view CommunityView 1"
292
- # "snmp-server view CommunityView 1.3.6.1.6.3"
293
- # "snmp-server view CommunityView 1.3.6.1.6.3.1"
294
- # "snmp-server view restricted 1.3.6.1.2.1.1"
295
- # "snmp-server view restricted 1.3.6.1.2.1.11"
296
- # "snmp-server view restricted 1.3.6.1.6.3.10.2.1"
297
- # "snmp-server view restricted 1.3.6.1.6.3.11.2.1"
298
- # "snmp-server view restricted 1.3.6.1.6.3.15.1.1"
299
- # "sntp"
300
- # "sntp interval"
301
- # "spanning-tree mode"
302
- # "spanning-tree mst"
303
- # "ssh user root authentication-method"
304
- # "username root password 7"
305
- # "username root privilege"
306
- #
307
-
308
-
309
- @result.add("snmp-server name", Ciscian::SingleValueVerb).add(@result.host.name)
254
+ @result.add("snmp-server name").add(@result.host.name)
310
255
  @result.host.interfaces.values.each do |iface|
311
256
  next unless iface.delegate.address
312
257
  iface.delegate.address.routes.each do |route|
313
258
  ip = route.dst.ipv6? ? "ipv6" : "ip"
314
- @result.add("#{ip} route #{route.dst.to_string} vlan#{iface.delegate.vlan_id} #{route.via.to_s}", Ciscian::SingleValueVerb)
259
+ @result.add("#{ip} route #{route.dst.to_string.upcase} vlan#{iface.delegate.vlan_id} #{route.via.to_s.upcase}", Ciscian::SingleValueVerb)
315
260
  end
316
261
  end
317
262
  end
318
263
 
319
- def add_device(device)
320
- @result.add("interface #{expand_device_name(device)}") do |section|
321
- section.add("flowcontrol").add("off")
322
- section.add("max-rcv-frame-size").add(device.delegate.mtu)
323
- section.add("snmp trap").add("link-status")
264
+ def add_device(device, bond=false)
265
+ @result.add("interface #{expand_device_name(device)}", NestedSection) do |section|
324
266
  section.add("switchport mode").add("trunk")
267
+ unless bond
268
+ section.add("flowcontrol").add("off")
269
+ section.add("max-rcv-frame-size").add(device.delegate.mtu)
270
+ section.add("snmp trap").add("link-status")
271
+ end
325
272
  end
326
273
  end
327
274
 
328
275
  def add_bond(bond)
329
276
  bond.interfaces.each do |iface|
330
- @result.add("interface #{expand_device_name(iface)}") do |section|
277
+ @result.add("interface #{expand_device_name(iface)}", NestedSection) do |section|
331
278
  section.add("channel-group", ChannelGroupVerb).add({"{+channel}" => [bond.name[2..-1]]})
332
279
  end
333
280
  end
281
+ self.add_device(bond, true)
334
282
  end
335
283
 
336
284
  def add_vlan(vlan)
337
- @result.add("vlan #{vlan.delegate.vlan_id}") do |section|
285
+ @result.add("vlan #{vlan.delegate.vlan_id}", NestedSection) do |section|
338
286
  next unless vlan.delegate.description && !vlan.delegate.description.empty?
339
287
  throw "vlan name too long, max 32 chars" if vlan.delegate.description.length > 32
340
288
  section.add("name").add(vlan.delegate.description)
341
289
  end
342
- @result.add("interface vlan #{vlan.delegate.vlan_id}") do |section|
290
+ @result.add("interface vlan #{vlan.delegate.vlan_id}", NestedSection) do |section|
343
291
  if vlan.delegate.address
344
292
  if vlan.delegate.address.first_ipv4
345
- section.add("ip address").add(vlan.delegate.address.first_ipv4.to_string)
293
+ section.add("ip address").add(vlan.delegate.address.first_ipv4.to_string.upcase)
346
294
  elsif vlan.delegate.address.dhcpv4?
347
295
  section.add("ip address").add("dhcp-bootp")
348
296
  end
349
297
  if vlan.delegate.address.first_ipv6
350
- section.add("ipv6 address").add(vlan.delegate.address.first_ipv6.to_string)
298
+ section.add("ipv6 address").add(vlan.delegate.address.first_ipv6.to_string.upcase)
351
299
  elsif vlan.delegate.address.dhcpv6?
352
300
  section.add("ipv6 address").add("dhcp-bootp")
353
301
  end
@@ -356,7 +304,7 @@ module Construqt
356
304
 
357
305
  vlan_id=vlan.delegate.vlan_id
358
306
  vlan.interfaces.each do |iface|
359
- @result.add("interface #{expand_device_name(iface)}") do |section|
307
+ @result.add("interface #{expand_device_name(iface)}", NestedSection) do |section|
360
308
  section.add("switchport trunk allowed vlan", Ciscian::RangeVerb).add(vlan_id)
361
309
  unless iface.template.is_tagged?(vlan_id)
362
310
  section.add("switchport trunk native vlan").add(vlan_id)