construqt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/construqt/addresses.rb +204 -0
- data/lib/construqt/bgps.rb +164 -0
- data/lib/construqt/cables.rb +47 -0
- data/lib/construqt/firewalls.rb +247 -0
- data/lib/construqt/flavour/ciscian/ciscian.rb +687 -0
- data/lib/construqt/flavour/ciscian/dialect_dlink-dgs15xx.rb +235 -0
- data/lib/construqt/flavour/ciscian/dialect_hp-2510g.rb +114 -0
- data/lib/construqt/flavour/delegates.rb +448 -0
- data/lib/construqt/flavour/flavour.rb +97 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik.rb +417 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_bgp.rb +134 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_interface.rb +79 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_ipsec.rb +65 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_result.rb +182 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_schema.rb +355 -0
- data/lib/construqt/flavour/plantuml/plantuml.rb +462 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu.rb +381 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_bgp.rb +117 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_dns.rb +97 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb +300 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_ipsec.rb +144 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_opvn.rb +60 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_result.rb +537 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_services.rb +115 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_vrrp.rb +52 -0
- data/lib/construqt/flavour/unknown/unknown.rb +175 -0
- data/lib/construqt/hostid.rb +42 -0
- data/lib/construqt/hosts.rb +98 -0
- data/lib/construqt/interfaces.rb +166 -0
- data/lib/construqt/ipsecs.rb +64 -0
- data/lib/construqt/networks.rb +81 -0
- data/lib/construqt/regions.rb +32 -0
- data/lib/construqt/resource.rb +42 -0
- data/lib/construqt/services.rb +53 -0
- data/lib/construqt/tags.rb +61 -0
- data/lib/construqt/templates.rb +37 -0
- data/lib/construqt/tests/test_addresses.rb +50 -0
- data/lib/construqt/tests/test_bgps.rb +24 -0
- data/lib/construqt/tests/test_hostid.rb +32 -0
- data/lib/construqt/tests/test_hosts.rb +23 -0
- data/lib/construqt/tests/test_utils.rb +76 -0
- data/lib/construqt/users.rb +19 -0
- data/lib/construqt/util.rb +163 -0
- data/lib/construqt/version.rb +3 -0
- data/lib/construqt/vlans.rb +51 -0
- data/lib/construqt.rb +92 -0
- metadata +105 -0
@@ -0,0 +1,417 @@
|
|
1
|
+
require_relative 'flavour_mikrotik_schema.rb'
|
2
|
+
require_relative 'flavour_mikrotik_ipsec.rb'
|
3
|
+
require_relative 'flavour_mikrotik_bgp.rb'
|
4
|
+
require_relative 'flavour_mikrotik_result.rb'
|
5
|
+
require_relative 'flavour_mikrotik_interface.rb'
|
6
|
+
|
7
|
+
|
8
|
+
module Construqt
|
9
|
+
module Flavour
|
10
|
+
module Mikrotik
|
11
|
+
|
12
|
+
|
13
|
+
def self.name
|
14
|
+
'mikrotik'
|
15
|
+
end
|
16
|
+
|
17
|
+
Flavour.add(self)
|
18
|
+
|
19
|
+
class Device < OpenStruct
|
20
|
+
def initialize(cfg)
|
21
|
+
super(cfg)
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_config(host, iface)
|
25
|
+
binding.pry if iface.default_name.nil? || iface.default_name.empty?
|
26
|
+
iface = iface.delegate
|
27
|
+
default = {
|
28
|
+
"l2mtu" => Schema.int.default(1590),
|
29
|
+
"mtu" => Schema.int.default(1500),
|
30
|
+
"name" => Schema.identifier.default("dummy"),
|
31
|
+
"default-name" => Schema.identifier.required.key.noset
|
32
|
+
}
|
33
|
+
host.result.render_mikrotik_set_by_key(default, {
|
34
|
+
"l2mtu" => iface.mtu,
|
35
|
+
"mtu" => iface.mtu,
|
36
|
+
"name" => iface.name,
|
37
|
+
"default-name" => iface.default_name
|
38
|
+
}, "interface")
|
39
|
+
Interface.build_config(host, iface)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Vrrp < OpenStruct
|
44
|
+
def initialize(cfg)
|
45
|
+
super(cfg)
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_config(host, iface)
|
49
|
+
iface = iface.delegate
|
50
|
+
default = {
|
51
|
+
"interface" => Schema.identifier.required,
|
52
|
+
"name" => Schema.identifier.key.required,
|
53
|
+
"priority" => Schema.int.required,
|
54
|
+
"v3-protocol" => Schema.identifier.required,
|
55
|
+
"vrid" => Schema.int.required
|
56
|
+
}
|
57
|
+
host.result.render_mikrotik(default, {
|
58
|
+
"interface" => iface.interface.name,
|
59
|
+
"name" => iface.name,
|
60
|
+
"priority" => iface.interface.priority,
|
61
|
+
"v3-protocol" => "ipv6",
|
62
|
+
"vrid" => iface.vrid
|
63
|
+
}, "interface", "vrrp")
|
64
|
+
Interface.build_config(host, iface)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Bond < OpenStruct
|
69
|
+
def initialize(cfg)
|
70
|
+
super(cfg)
|
71
|
+
end
|
72
|
+
|
73
|
+
def scheduler_hack(host, iface)
|
74
|
+
#binding.pry if iface.name=="sw12"
|
75
|
+
return [] unless iface.interfaces.find{|iface| iface.class.kind_of? self.class }
|
76
|
+
|
77
|
+
system_script_schema = {
|
78
|
+
"name" => Schema.identifier.key.required,
|
79
|
+
"source" => Schema.source.required
|
80
|
+
}
|
81
|
+
host.result.render_mikrotik(system_script_schema, {
|
82
|
+
"no_auto_disable" => true,
|
83
|
+
"name" => "disable-#{iface.name}",
|
84
|
+
"source" => <<SRC
|
85
|
+
/interface bonding disable [ find name=#{iface.name} ]
|
86
|
+
/system scheduler enable [ find name=enable-#{iface.name} ]
|
87
|
+
SRC
|
88
|
+
}, "system", "script")
|
89
|
+
|
90
|
+
or_condition = "(" + iface.interfaces.map{|iface| "name=#{iface.name}"}.join(" or ") + ")"
|
91
|
+
host.result.render_mikrotik(system_script_schema, {
|
92
|
+
"no_auto_disable" => true,
|
93
|
+
"name" => "enable-#{iface.name}",
|
94
|
+
"source" => <<SRC
|
95
|
+
:local run [ /interface bonding find running=yes and #{or_condition}]
|
96
|
+
:if ($run!="") do={
|
97
|
+
/interface bonding enable [find name=sw12]
|
98
|
+
/system schedule disable [ find name=enable-sw12 ]
|
99
|
+
}
|
100
|
+
SRC
|
101
|
+
}, "system", "script")
|
102
|
+
|
103
|
+
system_scheduler_script = {
|
104
|
+
"name" => Schema.identifier.key.required,
|
105
|
+
"on-event" => Schema.identifier.required,
|
106
|
+
"start-time" => Schema.identifier.null,
|
107
|
+
"interval" => Schema.interval.null,
|
108
|
+
"disabled" => Schema.boolean.default(false)
|
109
|
+
}
|
110
|
+
host.result.render_mikrotik(system_scheduler_script, {
|
111
|
+
"name" => "disable-#{iface.name}",
|
112
|
+
"on-event" => "disable-#{iface.name}",
|
113
|
+
"start-time" => "startup"
|
114
|
+
}, "system", "scheduler")
|
115
|
+
|
116
|
+
host.result.render_mikrotik(system_scheduler_script, {
|
117
|
+
"name" => "enable-#{iface.name}",
|
118
|
+
"on-event" => "enable-#{iface.name}",
|
119
|
+
"interval" => "00:00:10",
|
120
|
+
"disabled" => true
|
121
|
+
}, "system", "scheduler")
|
122
|
+
end
|
123
|
+
|
124
|
+
def build_config(host, iface)
|
125
|
+
iface = iface.delegate
|
126
|
+
default = {
|
127
|
+
"mode" => Schema.string.default("active-backup"),
|
128
|
+
"mtu" => Schema.int.required,
|
129
|
+
"name" => Schema.identifier.required.key,
|
130
|
+
"slaves" => Schema.identifiers.required,
|
131
|
+
}
|
132
|
+
host.result.render_mikrotik(default, {
|
133
|
+
"mtu" => iface.mtu,
|
134
|
+
"name" => iface.name,
|
135
|
+
"mode" => iface.mode,
|
136
|
+
"slaves" => iface.interfaces.map{|iface| iface.name}.join(',')
|
137
|
+
}, "interface", "bonding")
|
138
|
+
Interface.build_config(host, iface)
|
139
|
+
scheduler_hack(host, iface)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class Vlan < OpenStruct
|
144
|
+
def initialize(cfg)
|
145
|
+
super(cfg)
|
146
|
+
end
|
147
|
+
|
148
|
+
def build_config(host, iface)
|
149
|
+
iface = iface.delegate
|
150
|
+
default = {
|
151
|
+
"interface" => Schema.identifier.required,
|
152
|
+
"mtu" => Schema.int.required,
|
153
|
+
"name" => Schema.identifier.required.key,
|
154
|
+
"vlan-id" => Schema.int.required,
|
155
|
+
}
|
156
|
+
iface.interfaces.each do |vlan_iface|
|
157
|
+
host.result.render_mikrotik(default, {
|
158
|
+
"interface" => vlan_iface.name,
|
159
|
+
"mtu" => iface.mtu,
|
160
|
+
"name" => iface.name,
|
161
|
+
"vlan-id" => iface.vlan_id
|
162
|
+
}, "interface", "vlan")
|
163
|
+
end
|
164
|
+
Interface.build_config(host, iface)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
class Bridge < OpenStruct
|
169
|
+
def initialize(cfg)
|
170
|
+
super(cfg)
|
171
|
+
end
|
172
|
+
|
173
|
+
def build_config(host, iface)
|
174
|
+
iface = iface.delegate
|
175
|
+
default = {
|
176
|
+
"auto-mac" => Schema.boolean.default(true),
|
177
|
+
"mtu" => Schema.int.required,
|
178
|
+
"priority" => Schema.int.default(57344),
|
179
|
+
"name" => Schema.identifier.required.key
|
180
|
+
}
|
181
|
+
host.result.render_mikrotik(default, {
|
182
|
+
"mtu" => iface.mtu,
|
183
|
+
"name" => iface.name,
|
184
|
+
"priority" => iface.priority
|
185
|
+
}, "interface", "bridge")
|
186
|
+
iface.interfaces.each do |port|
|
187
|
+
host.result.render_mikrotik({
|
188
|
+
"bridge" => Schema.identifier.required.key,
|
189
|
+
"interface" => Schema.identifier.required.key
|
190
|
+
}, {
|
191
|
+
"interface" => port.name,
|
192
|
+
"bridge" => iface.name,
|
193
|
+
}, "interface", "bridge", "port")
|
194
|
+
end
|
195
|
+
Interface.build_config(host, iface)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
class Host < OpenStruct
|
200
|
+
def initialize(cfg)
|
201
|
+
super(cfg)
|
202
|
+
end
|
203
|
+
|
204
|
+
def footer(host)
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.header(host)
|
208
|
+
host = host.delegate
|
209
|
+
host.result.add(<<TESTNAME, nil, "system", "identity")
|
210
|
+
{
|
211
|
+
:local identity [get]
|
212
|
+
:if (($identity->"name") != "#{host.name}") do={
|
213
|
+
:put "Execute /system identity set name=#{host.name}"
|
214
|
+
:error ("The Script is for router #{host.name} this router named ".($identity->"name"))
|
215
|
+
} else={
|
216
|
+
:put "Configure #{host.name}"
|
217
|
+
}
|
218
|
+
}
|
219
|
+
TESTNAME
|
220
|
+
host.result.render_mikrotik_set_direct({ "name"=> Schema.identifier.required.key },
|
221
|
+
{ "name" => host.name }, "system", "identity")
|
222
|
+
|
223
|
+
host.result.render_mikrotik_set_direct({ "time-zone-name"=> Schema.identifier.required.key },
|
224
|
+
{ "time-zone-name" => host.time_zone||'MET' }, "system", "clock")
|
225
|
+
|
226
|
+
dns = host.region.network.dns_resolver.nameservers.ips
|
227
|
+
host.result.render_mikrotik_set_direct({"servers"=>Schema.addresses.required.key },
|
228
|
+
{ "servers"=> dns }, "ip", "dns")
|
229
|
+
|
230
|
+
host.result.add("add", nil, "tool", "graphing", "interface")
|
231
|
+
|
232
|
+
host.result.add("set [ find name!=ssh && name!=www-ssl ] disabled=yes", nil, "ip", "service")
|
233
|
+
host.result.add("set [ find ] address=#{host.id.first_ipv6.first_ipv6}", nil, "ip", "service")
|
234
|
+
host.result.add("set [ find name!=admin ] comment=REMOVE", nil, "user")
|
235
|
+
|
236
|
+
host.result.render_mikrotik({
|
237
|
+
"name" => Schema.identifier.required.key,
|
238
|
+
"enc-algorithms" => Schema.identifier.default("aes-256-cbc"),
|
239
|
+
"lifetime" => Schema.interval.default("00:01:00"),
|
240
|
+
"pfs-group"=> Schema.identifier.default("modp1536")
|
241
|
+
}, {"name" => "s2b-proposal"}, "ip", "ipsec", "proposal")
|
242
|
+
host.result.add("", "default=yes", "ip", "ipsec", "proposal")
|
243
|
+
host.result.add("", "template=yes", "ip", "ipsec", "policy")
|
244
|
+
host.result.add("", "name=default", "routing", "bgp", "instance")
|
245
|
+
host.result.add_remove_pre_condition('comment~"CONSTRUQT\$"', "ip", "address")
|
246
|
+
host.result.add_remove_pre_condition('comment~"CONSTRUQT\$"', "ip", "route")
|
247
|
+
host.result.add_remove_pre_condition('comment~"CONSTRUQT\$"', "ipv6", "address")
|
248
|
+
host.result.add_remove_pre_condition('comment~"CONSTRUQT\$"', "ipv6", "route")
|
249
|
+
host.region.users.all.each do |u|
|
250
|
+
host.result.add(<<OUT, nil, "user")
|
251
|
+
{
|
252
|
+
:local found [find name=#{u.name.inspect} ]
|
253
|
+
:if ($found = "") do={
|
254
|
+
add comment=#{u.full_name.inspect} name=#{u.name} password=#{host.region.hosts.default_password} group=full
|
255
|
+
} else={
|
256
|
+
set $found comment=#{u.full_name.inspect}
|
257
|
+
}
|
258
|
+
}
|
259
|
+
OUT
|
260
|
+
end
|
261
|
+
|
262
|
+
host.result.add("remove [find comment=REMOVE ]", nil, "user" )
|
263
|
+
host.result.add("set [ find name=admin] disable=yes", nil, "user")
|
264
|
+
end
|
265
|
+
|
266
|
+
def build_config(host, unused)
|
267
|
+
ret = ["# host"]
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
class Ovpn < OpenStruct
|
272
|
+
def initialize(cfg)
|
273
|
+
super(cfg)
|
274
|
+
end
|
275
|
+
|
276
|
+
def build_config(host, iface)
|
277
|
+
throw "ovpn not impl"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
class Gre < OpenStruct
|
282
|
+
def initialize(cfg)
|
283
|
+
super(cfg)
|
284
|
+
end
|
285
|
+
|
286
|
+
def set_interface_gre(host, cfg)
|
287
|
+
default = {
|
288
|
+
"name"=>Schema.identifier.required.key,
|
289
|
+
"local-address"=>Schema.address.required,
|
290
|
+
"remote-address"=>Schema.address.required,
|
291
|
+
"dscp"=>Schema.identifier.default("inherit"),
|
292
|
+
"mtu"=>Schema.int.default(1476)
|
293
|
+
# "l2mtu"=>Scheme.int.default(65535)
|
294
|
+
}
|
295
|
+
host.result.render_mikrotik(default, cfg, "interface", "gre")
|
296
|
+
end
|
297
|
+
|
298
|
+
def set_interface_gre6(host, cfg)
|
299
|
+
default = {
|
300
|
+
"name"=>Schema.identifier.required.key,
|
301
|
+
"local-address"=>Schema.address.required,
|
302
|
+
"remote-address"=>Schema.address.required,
|
303
|
+
"mtu"=>Schema.int.default(1456)
|
304
|
+
# "l2mtu"=>Schema.int.default(65535)
|
305
|
+
}
|
306
|
+
host.result.render_mikrotik(default, cfg, "interface", "gre6")
|
307
|
+
end
|
308
|
+
|
309
|
+
def build_config(host, iface)
|
310
|
+
iface = iface.delegate
|
311
|
+
#puts "iface.name=>#{iface.name}"
|
312
|
+
#binding.pry
|
313
|
+
#iname = Util.clean_if("gre6", "#{iface.name}")
|
314
|
+
if iface.local.first_ipv6 && iface.remote.first_ipv6
|
315
|
+
set_interface_gre6(host, "name"=> iface.name,
|
316
|
+
"local-address"=>iface.local.first_ipv6,
|
317
|
+
"remote-address"=>iface.remote.first_ipv6)
|
318
|
+
else
|
319
|
+
set_interface_gre(host, "name"=> iface.name,
|
320
|
+
"local-address"=>iface.local.first_ipv4,
|
321
|
+
"remote-address"=>iface.remote.first_ipv4)
|
322
|
+
end
|
323
|
+
Interface.build_config(host, iface)
|
324
|
+
|
325
|
+
#Mikrotik.set_ipv6_address(host, "address"=>iface.address.first_ipv6.to_string, "interface" => iname)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def set_ipv6_address(host, cfg)
|
330
|
+
default = {
|
331
|
+
"address"=>Schema.network.required,
|
332
|
+
"interface"=>Schema.identifier.required,
|
333
|
+
"comment" => Schema.string.required.key,
|
334
|
+
"advertise"=>Schema.boolean.default(false)
|
335
|
+
}
|
336
|
+
cfg['comment'] = "#{cfg['interface']}-#{cfg['address']}"
|
337
|
+
host.result.render_mikrotik(default, cfg, "ipv6", "address")
|
338
|
+
end
|
339
|
+
|
340
|
+
class Template < OpenStruct
|
341
|
+
def initialize(cfg)
|
342
|
+
super(cfg)
|
343
|
+
end
|
344
|
+
|
345
|
+
def build_config(host, iface)
|
346
|
+
throw "template not impl"
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
def self.compress_address(val)
|
351
|
+
return val.compressed if val.ipv4?
|
352
|
+
found = 0
|
353
|
+
val.groups.map do |i|
|
354
|
+
if found > 0 && i != 0
|
355
|
+
found = -1
|
356
|
+
end
|
357
|
+
|
358
|
+
if found == 0 && i == 0
|
359
|
+
found += 1
|
360
|
+
""
|
361
|
+
elsif found > 0 && i == 0
|
362
|
+
found += 1
|
363
|
+
nil
|
364
|
+
else
|
365
|
+
i.to_s 16
|
366
|
+
end
|
367
|
+
end.compact.join(":").sub(/:+$/, '::')
|
368
|
+
end
|
369
|
+
|
370
|
+
def self.clazzes
|
371
|
+
{
|
372
|
+
"opvn" => Ovpn,
|
373
|
+
"gre" => Gre,
|
374
|
+
"host" => Host,
|
375
|
+
"device"=> Device,
|
376
|
+
"vrrp" => Vrrp,
|
377
|
+
"bridge" => Bridge,
|
378
|
+
"bond" => Bond,
|
379
|
+
"vlan" => Vlan,
|
380
|
+
"result" => Result,
|
381
|
+
"template" => Template,
|
382
|
+
"bgp" => Ipsec,
|
383
|
+
"ipsec" => Bgp
|
384
|
+
}
|
385
|
+
end
|
386
|
+
def self.clazz(name)
|
387
|
+
ret = self.clazzes[name]
|
388
|
+
throw "class not found #{name}" unless ret
|
389
|
+
ret
|
390
|
+
end
|
391
|
+
|
392
|
+
def self.create_host(name, cfg)
|
393
|
+
cfg['name'] = name
|
394
|
+
cfg['result'] = nil
|
395
|
+
host = Host.new(cfg)
|
396
|
+
host.result = Result.new(host)
|
397
|
+
host
|
398
|
+
end
|
399
|
+
|
400
|
+
def self.create_interface(name, cfg)
|
401
|
+
cfg['name'] = name
|
402
|
+
clazz(cfg['clazz']).new(cfg)
|
403
|
+
#cfg['name'] = name
|
404
|
+
#iface = Interface.new(cfg)
|
405
|
+
#iface
|
406
|
+
end
|
407
|
+
|
408
|
+
def self.create_bgp(cfg)
|
409
|
+
Bgp.new(cfg)
|
410
|
+
end
|
411
|
+
|
412
|
+
def self.create_ipsec(cfg)
|
413
|
+
Ipsec.new(cfg)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module Construqt
|
2
|
+
module Flavour
|
3
|
+
module Mikrotik
|
4
|
+
|
5
|
+
class Bgp < OpenStruct
|
6
|
+
def initialize(cfg)
|
7
|
+
super(cfg)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.write_filter(host)
|
11
|
+
Bgps.filters.each do |filter|
|
12
|
+
v4_name="v4-#{filter.name}"
|
13
|
+
v6_name="v6-#{filter.name}"
|
14
|
+
host.result.add("set [ find chain=#{v4_name.inspect} ] comment=to_remove", nil, "routing", "filter")
|
15
|
+
host.result.add("set [ find chain=#{v6_name.inspect} ] comment=to_remove", nil, "routing", "filter")
|
16
|
+
filter.list.each do |rule|
|
17
|
+
rule['network'].ips.each do |ip|
|
18
|
+
prefix_len = ""
|
19
|
+
if rule['prefix_length']
|
20
|
+
prefix_len = "prefix-length=#{rule['prefix_length'].first}-#{rule['prefix_length'].last}"
|
21
|
+
end
|
22
|
+
|
23
|
+
host.result.add("add action=#{rule['rule']} chain=v#{ip.ipv4? ? '4':'6'}-#{filter.name} prefix=#{ip.to_string} #{prefix_len}", nil, "routing", "filter")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
host.result.add("remove [ find comment=to_remove && (chain=#{v4_name.inspect} || chain=#{v6_name.inspect}) ]", nil, "routing", "filter")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.set_routing_bgp_instance(host, cfg)
|
32
|
+
default = {
|
33
|
+
"name" => Schema.string.required,
|
34
|
+
"as" => Schema.int.required.key,
|
35
|
+
"router-id"=> Schema.address.required,
|
36
|
+
"redistribute-connected" => Schema.boolean.default(true),
|
37
|
+
"redistribute-static" => Schema.boolean.default(true),
|
38
|
+
"redistribute-rip" => Schema.boolean.default(false),
|
39
|
+
"redistribute-ospf" => Schema.boolean.default(false),
|
40
|
+
"redistribute-other-bgp" => Schema.boolean.default(false),
|
41
|
+
"out-filter"=>Schema.identifier.default(nil),
|
42
|
+
"client-to-client-reflection"=>Schema.boolean.default(true),
|
43
|
+
"ignore-as-path-len"=>Schema.boolean.default(false),
|
44
|
+
"routing-table"=>Schema.identifier.default(nil),
|
45
|
+
"comment"=>Schema.string.default(nil)
|
46
|
+
}
|
47
|
+
host.result.render_mikrotik(default, cfg, "routing", "bgp", "instance")
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.write_peer(host)
|
51
|
+
as_s = {}
|
52
|
+
Bgps.connections.each do |bgp|
|
53
|
+
as_s[bgp.left.as] ||= OpenStruct.new(:host => host) if bgp.left.my.host == host
|
54
|
+
as_s[bgp.right.as] ||= OpenStruct.new(:host => host) if bgp.right.my.host == host
|
55
|
+
end
|
56
|
+
|
57
|
+
as_s.each do |as, val|
|
58
|
+
host = val.host
|
59
|
+
#puts "****** #{host.name}"
|
60
|
+
digest=Digest::SHA256.hexdigest("#{host.name} #{host.id.first_ipv4.first_ipv4.to_s} #{as}")
|
61
|
+
net = host.id.first_ipv4.first_ipv4.to_s.split('.')[0..1]
|
62
|
+
net.push(digest[0..1].to_i(16).to_s)
|
63
|
+
net.push(digest[-2..-1].to_i(16).to_s)
|
64
|
+
router_id = IPAddress.parse(net.join('.')) # hack ..... achtung
|
65
|
+
cfg = as.to_h.inject({}){|r,(k,v)| r[k.to_s]=v; r }.merge({
|
66
|
+
"comment" => as.description,
|
67
|
+
"name"=>"#{as.name}",
|
68
|
+
"as" => as.num,
|
69
|
+
"router-id" => router_id}).inject({}) {|r,p| r[p.first.to_s] = p.last; r}
|
70
|
+
#puts ">>>#{cfg.inspect}"
|
71
|
+
set_routing_bgp_instance(host, cfg)
|
72
|
+
end
|
73
|
+
|
74
|
+
#puts ">>>>>> #{as_s.keys}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.header(host)
|
78
|
+
#binding.pry if host.name == "s2b-l3-r01"
|
79
|
+
self.write_peer(host)
|
80
|
+
self.write_filter(host)
|
81
|
+
end
|
82
|
+
|
83
|
+
def set_routing_bgp_peer(cfg)
|
84
|
+
default = {
|
85
|
+
"name" => Schema.identifier.required.key,
|
86
|
+
"instance" => Schema.identifier.required,
|
87
|
+
"remote-address" => Schema.address.required,
|
88
|
+
"remote-as" => Schema.int.required,
|
89
|
+
"in-filter" => Schema.identifier.required,
|
90
|
+
"out-filter" => Schema.identifier.required,
|
91
|
+
"tcp-md5-key" => Schema.string.default(""),
|
92
|
+
"nexthop-choice" => Schema.identifier.default("force-self"),
|
93
|
+
"multihop" => Schema.boolean.default(false),
|
94
|
+
"route-reflect" => Schema.boolean.default(false),
|
95
|
+
"hold-time" => Schema.identifier.default("3m"),
|
96
|
+
"ttl" => Schema.identifier.default("default"),
|
97
|
+
"address-families" => Schema.identifier.required,
|
98
|
+
"default-originate" => Schema.identifier.default("never"),
|
99
|
+
"remove-private-as" => Schema.boolean.default(false),
|
100
|
+
"as-override" => Schema.boolean.default(false),
|
101
|
+
"passive" => Schema.boolean.default(false),
|
102
|
+
"use-bfd" => Schema.boolean.default(true),
|
103
|
+
"comment" => Schema.string.null
|
104
|
+
}
|
105
|
+
self.host.result.render_mikrotik(default, cfg, "routing", "bgp", "peer")
|
106
|
+
end
|
107
|
+
|
108
|
+
def build_config(unused, unused1)
|
109
|
+
#binding.pry
|
110
|
+
#puts "as=>#{self.as} #{self.other.my.host.name}"
|
111
|
+
self.other.my.address.first_ipv4 && set_routing_bgp_peer("name"=> "v4-#{self.other.my.host.name}-#{self.as.name}",
|
112
|
+
"comment" => "v4-#{self.other.my.host.name}-#{self.as.name}",
|
113
|
+
"instance" => "#{self.as.name}",
|
114
|
+
"remote-as" => self.other.as.num,
|
115
|
+
"address-families" => "ip",
|
116
|
+
"default-originate" => self.default_originate,
|
117
|
+
"remote-address" => self.other.my.address.first_ipv4,
|
118
|
+
"tcp-md5-key" => self.cfg.password,
|
119
|
+
"in-filter" => "v4-"+self.filter['in'].name,
|
120
|
+
"out-filter" => "v4-"+self.filter['out'].name)
|
121
|
+
self.other.my.address.first_ipv6 && set_routing_bgp_peer("name"=> "v6-#{self.other.my.host.name}-#{self.as.name}",
|
122
|
+
"comment" => "v6-#{self.other.my.host.name}-#{self.as.name}",
|
123
|
+
"instance" => "#{self.as.name}",
|
124
|
+
"remote-as" => self.other.as.num,
|
125
|
+
"address-families" => "ipv6",
|
126
|
+
"remote-address" => self.other.my.address.first_ipv6,
|
127
|
+
"tcp-md5-key" => self.cfg.password,
|
128
|
+
"in-filter" => "v6-"+self.filter['in'].name,
|
129
|
+
"out-filter" => "v6-"+self.filter['out'].name)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Construqt
|
2
|
+
module Flavour
|
3
|
+
module Mikrotik
|
4
|
+
|
5
|
+
class Interface
|
6
|
+
|
7
|
+
def self.render_ip(host, iface, ip)
|
8
|
+
cfg = {
|
9
|
+
"address" => ip,
|
10
|
+
"interface" => iface.name
|
11
|
+
}
|
12
|
+
if ip.ipv6?
|
13
|
+
default = {
|
14
|
+
"address" => Schema.addrprefix.required,
|
15
|
+
"interface" => Schema.identifier.required,
|
16
|
+
"advertise" => Schema.boolean.default(false),
|
17
|
+
"comment" => Schema.string.required.key
|
18
|
+
}
|
19
|
+
cfg['comment'] = "#{cfg['interface']}-#{cfg['address']}-CONSTRUQT"
|
20
|
+
#puts ">>>>>>>> #{cfg.inspect}"
|
21
|
+
host.result.render_mikrotik(default, cfg, "ipv6", "address")
|
22
|
+
else
|
23
|
+
default = {
|
24
|
+
"address" => Schema.addrprefix.required,
|
25
|
+
"interface" => Schema.identifier.required,
|
26
|
+
"comment" => Schema.string.required.key
|
27
|
+
}
|
28
|
+
cfg['comment'] = "#{cfg['interface']}-#{cfg['address']}-CONSTRUQT"
|
29
|
+
host.result.render_mikrotik(default, cfg, "ip", "address")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.render_route(host, iface, rt)
|
34
|
+
throw "dst via mismatch #{rt}" if rt.type.nil? and !(rt.dst.ipv6? == rt.via.ipv6? or rt.dst.ipv4? == rt.via.ipv4?)
|
35
|
+
cfg = {
|
36
|
+
"dst-address" => rt.dst,
|
37
|
+
"gateway" => rt.via,
|
38
|
+
}
|
39
|
+
if rt.type.nil?
|
40
|
+
cfg['gateway'] = rt.via
|
41
|
+
else
|
42
|
+
cfg['type'] = rt.type
|
43
|
+
end
|
44
|
+
|
45
|
+
cfg['distance'] = rt.metric if rt.metric
|
46
|
+
default = {
|
47
|
+
"dst-address" => Schema.network.required,
|
48
|
+
"gateway" => Schema.address,
|
49
|
+
"type" => Schema.identifier,
|
50
|
+
"distance" => Schema.int,
|
51
|
+
"comment" => Schema.string.required.key
|
52
|
+
}
|
53
|
+
cfg['comment'] = "#{cfg['dst-address']} via #{cfg['gateway']} CONSTRUQT"
|
54
|
+
if rt.dst.ipv6?
|
55
|
+
host.result.render_mikrotik(default, cfg, "ipv6", "route")
|
56
|
+
else
|
57
|
+
host.result.render_mikrotik(default, cfg, "ip", "route")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.build_config(host, iface)
|
62
|
+
#name = File.join(host.name, "interface", "device")
|
63
|
+
#ret = []
|
64
|
+
#ret += self.clazz.build_config(host, iface||self)
|
65
|
+
if !(iface.address.nil? || iface.address.ips.empty?)
|
66
|
+
iface.address.ips.each do |ip|
|
67
|
+
render_ip(host, iface, ip)
|
68
|
+
end
|
69
|
+
|
70
|
+
iface.address.routes.each do |rt|
|
71
|
+
render_route(host, iface, rt)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
#ret
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|