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,53 @@
|
|
1
|
+
module Construqt
|
2
|
+
class Services
|
3
|
+
|
4
|
+
class DhcpV4Relay
|
5
|
+
attr_accessor :servers, :name
|
6
|
+
def initialize(name)
|
7
|
+
self.name = name
|
8
|
+
self.servers = []
|
9
|
+
end
|
10
|
+
def add_server(ip)
|
11
|
+
ip = IPAddress.parse(ip)
|
12
|
+
throw "ip must be a v4 address" unless ip.ipv4?
|
13
|
+
self.servers << ip
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class DhcpV6Relay
|
18
|
+
attr_accessor :servers, :name
|
19
|
+
def initialize(name)
|
20
|
+
self.name = name
|
21
|
+
self.servers = []
|
22
|
+
end
|
23
|
+
def add_server(ip)
|
24
|
+
ip = IPAddress.parse(ip)
|
25
|
+
throw "ip must be a v6 address" unless ip.ipv6?
|
26
|
+
self.servers << ip
|
27
|
+
self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
class Radvd
|
31
|
+
attr_accessor :servers, :name
|
32
|
+
def initialize(name)
|
33
|
+
self.name = name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@services = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
def find(name)
|
42
|
+
found = @services[name]
|
43
|
+
throw "service with name #{name} not found" unless found
|
44
|
+
found
|
45
|
+
end
|
46
|
+
|
47
|
+
def add(service)
|
48
|
+
@services[service.name] = service
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
module Construqt
|
3
|
+
module Tags
|
4
|
+
@tags = {}
|
5
|
+
@object_id_tags = {}
|
6
|
+
def self.add(tag_str, &block)
|
7
|
+
(name, *tags) = tag_str.split(/\s*#\s*/)
|
8
|
+
obj = block.call(name, tags)
|
9
|
+
#binding.pry
|
10
|
+
tags && tags.uniq.each do |tag|
|
11
|
+
@tags[tag] ||= []
|
12
|
+
@tags[tag] << obj unless @tags[tag].include?(obj)
|
13
|
+
end
|
14
|
+
if obj.respond_to? :tags
|
15
|
+
obj.tags = tags
|
16
|
+
end
|
17
|
+
@object_id_tags[obj.object_id] ||= []
|
18
|
+
@object_id_tags[obj.object_id] = (@object_id_tags[obj.object_id] + tags).uniq
|
19
|
+
[name, obj]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from(obj)
|
23
|
+
@object_id_tags[obj.object_id]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.find(tag, clazz = nil)
|
27
|
+
#binding.pry
|
28
|
+
ret = (@tags[tag] || []).select{|o| clazz.nil? || o.kind_of?(clazz) }
|
29
|
+
Construqt.logger.warn("tag #{tag} #{clazz.inspect} empty result") if ret.empty?
|
30
|
+
ret
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.ips_net(tag, family)
|
34
|
+
ip_module = family==Construqt::Addresses::IPV4 ? IPAddress::IPv4: IPAddress::IPv6
|
35
|
+
IPAddress::IPv4::summarize(*(@tags[tag]||[]).map do |obj|
|
36
|
+
if obj.kind_of?(IPAddress)
|
37
|
+
obj
|
38
|
+
elsif obj.respond_to? :ips
|
39
|
+
obj.ips
|
40
|
+
elsif obj.kind_of?(Construqt::Flavour::HostDelegate)
|
41
|
+
#binding.pry
|
42
|
+
res = obj.interfaces.values.map do |i|
|
43
|
+
i.delegate.address.ips.map do |a|
|
44
|
+
prefix = a.ipv4? ? 32 : 128
|
45
|
+
ret = IPAddress.parse("#{a.to_s}/#{prefix}")
|
46
|
+
puts "ADR=#{tag} #{ret.to_string} #{a.to_s}"
|
47
|
+
ret
|
48
|
+
end
|
49
|
+
end.flatten
|
50
|
+
puts "HOST=>#{tag} #{res.map{|i| i.to_string }}"
|
51
|
+
res
|
52
|
+
else
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end.flatten.compact.select do |i|
|
56
|
+
(family==Construqt::Addresses::IPV4 && i.ipv4?) ||
|
57
|
+
(family==Construqt::Addresses::IPV6 && i.ipv6?)
|
58
|
+
end)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module Construqt
|
3
|
+
class Templates
|
4
|
+
def initialize(region)
|
5
|
+
@region = region
|
6
|
+
@templates = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
class Template < OpenStruct
|
10
|
+
def initialize(cfg)
|
11
|
+
super(cfg)
|
12
|
+
end
|
13
|
+
|
14
|
+
def is_tagged?(vlan_id)
|
15
|
+
self.vlans.each do |vlan|
|
16
|
+
return vlan.tagged? if vlan.vlan_id == vlan_id
|
17
|
+
end
|
18
|
+
|
19
|
+
throw "vlan with id #{vlan_id} not found in template #{self}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def find(name)
|
24
|
+
ret = @templates[name]
|
25
|
+
throw "template with name #{name} not found" unless @templates[name]
|
26
|
+
ret
|
27
|
+
end
|
28
|
+
|
29
|
+
def add(name, cfg)
|
30
|
+
throw "template with name #{name} exists" if @templates[name]
|
31
|
+
cfg['name'] = name
|
32
|
+
ret = Template.new(cfg)
|
33
|
+
@templates[name] = ret
|
34
|
+
ret
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
addresses = Construqt::Addresses.new(7)
|
3
|
+
|
4
|
+
assert_eq(addresses.network, 7)
|
5
|
+
|
6
|
+
adr = addresses.create
|
7
|
+
|
8
|
+
assert_eq(addresses.all.length, 0)
|
9
|
+
|
10
|
+
adr.set_name("jojo")
|
11
|
+
assert_eq(adr.name, "jojo")
|
12
|
+
|
13
|
+
adr.name = "jojojo"
|
14
|
+
assert_eq(adr.name, "jojojo")
|
15
|
+
|
16
|
+
adr.add_ip("192.168.0.1")
|
17
|
+
assert_eq(adr.all.length, 1)
|
18
|
+
assert_eq(adr.v4s.length, 1)
|
19
|
+
assert_eq(adr.v6s.length, 0)
|
20
|
+
|
21
|
+
adr.add_ip("192.168.0.2")
|
22
|
+
assert_eq(adr.all.length, 2)
|
23
|
+
assert_eq(adr.v4s.length, 2)
|
24
|
+
assert_eq(adr.v6s.length, 0)
|
25
|
+
|
26
|
+
adr.add_ip("2000::/27")
|
27
|
+
assert_eq(adr.all.length, 3)
|
28
|
+
assert_eq(adr.v4s.length, 2)
|
29
|
+
assert_eq(adr.v6s.length, 1)
|
30
|
+
|
31
|
+
adr.add_ip("2001::/27")
|
32
|
+
assert_eq(adr.all.length, 4)
|
33
|
+
assert_eq(adr.v4s.length, 2)
|
34
|
+
assert_eq(adr.v6s.length, 2)
|
35
|
+
|
36
|
+
assert_eq(adr.first_ipv4, "192.168.0.1")
|
37
|
+
assert_eq(adr.first_ipv6, "2001::/27")
|
38
|
+
|
39
|
+
assert_eq(adr.dhcpv4?, false)
|
40
|
+
adr.add_ip(DHCPV4)
|
41
|
+
assert_eq(adr.dhcpv4?, true)
|
42
|
+
|
43
|
+
assert_eq(adr.dhcpv6?, false)
|
44
|
+
adr.add_ip(DHCPV6)
|
45
|
+
assert_eq(adr.dhcpv6?, true)
|
46
|
+
|
47
|
+
assert_eq(adr.loopback?, false)
|
48
|
+
adr.add_ip(LOOPBACK)
|
49
|
+
assert_eq(adr.loopback?, true)
|
50
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
Construqt::Bgps.add_as(93925993, "redistribute-connected" => true,
|
3
|
+
"redistribute-static" => true,
|
4
|
+
"redistribute-other-bgp" => true,
|
5
|
+
"description" => "test-93925993")
|
6
|
+
|
7
|
+
Construqt::Bgps.add_as(73925993, "redistribute-connected" => true,
|
8
|
+
"redistribute-static" => true,
|
9
|
+
"redistribute-other-bgp" => true,
|
10
|
+
"description" => "test-73925993")
|
11
|
+
|
12
|
+
Construqt::Bgps.connection("name_it",
|
13
|
+
"password" => "geheim",
|
14
|
+
"left" => {
|
15
|
+
"as" => Construqt::Bgps::find_as(93925993),
|
16
|
+
"my" => ipsec.left.interface,
|
17
|
+
"filter" => { "in" => Construqt::Bgps.find_filter('mgmt_net_in'), "out" => Construqt::Bgps.find_filter('mgmt_net_out') },
|
18
|
+
},
|
19
|
+
"right" => {
|
20
|
+
"as" => Construqt::Bgps::find_as(73925993),
|
21
|
+
"my" => ipsec.right.interface,
|
22
|
+
"filter" => { "in" => Construqt::Bgps.find_filter('mgmt_net_in'), "out" => Construqt::Bgps.find_filter('mgmt_net_out') },
|
23
|
+
}
|
24
|
+
)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
id = Construqt::HostId.create do |block|
|
4
|
+
assert_eq(block.interfaces.length, 0)
|
5
|
+
end
|
6
|
+
|
7
|
+
assert_eq(id.first_ipv6!, nil)
|
8
|
+
assert_eq(id.first_ipv4!, nil)
|
9
|
+
|
10
|
+
begin
|
11
|
+
id.first_ipv4
|
12
|
+
assert("should not happend")
|
13
|
+
raise
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
id.first_ipv6
|
18
|
+
assert("should not happend")
|
19
|
+
raise
|
20
|
+
end
|
21
|
+
|
22
|
+
iface = XXXXX
|
23
|
+
id = Construqt::HostId.create do |block|
|
24
|
+
assert_eq(block.interfaces.length, 0)
|
25
|
+
block.interfaces << iface
|
26
|
+
end
|
27
|
+
|
28
|
+
assert_eq(id.first_ipv6!, iface.first_ipv6)
|
29
|
+
assert_eq(id.first_ipv4!, iface.first_ipv4)
|
30
|
+
|
31
|
+
assert_eq(id.first_ipv6, iface.first_ipv6)
|
32
|
+
assert_eq(id.first_ipv4, iface.first_ipv4)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
hosts = Hosts.new(19)
|
3
|
+
|
4
|
+
assert_eq(hosts.region, 19)
|
5
|
+
|
6
|
+
hosts.set_default_password("9339")
|
7
|
+
assert_eq(hosts.default_password, "9339")
|
8
|
+
|
9
|
+
assert_eq(hosts.get_hosts.length, 0)
|
10
|
+
|
11
|
+
begin
|
12
|
+
hosts.add("test", "lutz" => "fuchs") do |host|
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
hosts.add("test", "lutz" => "fuchs") do |host|
|
18
|
+
end
|
19
|
+
assert("Should not happend")
|
20
|
+
raise
|
21
|
+
end
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
class Test
|
3
|
+
include Chainable
|
4
|
+
#def initialize
|
5
|
+
# puts ">>>test instance=#{"%x"%self.object_id} class=#{"%x"%self.class.object_id}"
|
6
|
+
#end
|
7
|
+
attr_reader :sideeffect
|
8
|
+
chainable_attr :bloed0
|
9
|
+
chainable_attr :bloed1
|
10
|
+
chainable_attr :test, 1, 2
|
11
|
+
chainable_attr :testbool, false, true
|
12
|
+
chainable_attr :testbool2, true, true
|
13
|
+
chainable_attr :testside, 1, 2, lambda {|i| @sideeffect ||= 9; @sideeffect += 1 }
|
14
|
+
end
|
15
|
+
class Test2
|
16
|
+
include Chainable
|
17
|
+
#def initialize
|
18
|
+
# puts ">>>test instance=#{"%x"%self.object_id} class=#{"%x"%self.class.object_id}"
|
19
|
+
#end
|
20
|
+
attr_reader :sideeffect
|
21
|
+
chainable_attr :bloed0
|
22
|
+
chainable_attr :bloed1
|
23
|
+
chainable_attr :test, 3, 4
|
24
|
+
chainable_attr :testbool, true, false
|
25
|
+
chainable_attr :testside, 3, 4, lambda {|i| @sideeffect ||= 5; @sideeffect += 1 }
|
26
|
+
end
|
27
|
+
def self.test
|
28
|
+
3.times do |i|
|
29
|
+
t = Test.new
|
30
|
+
#throw "chainable failed input_only" unless t.input_only? == true
|
31
|
+
#throw "chainable failed output_only" unless t.output_only? == true
|
32
|
+
|
33
|
+
#puts "#{i}=>#{t.testbool?} #{t.testbool2?}"
|
34
|
+
throw "chainable failed test should 2 #{t.get_test.inspect}" if t.get_test != 2
|
35
|
+
t.test
|
36
|
+
throw "chainable failed this should be 1 " if t.get_test != 1
|
37
|
+
t.test(3)
|
38
|
+
throw "chainable failed" if t.get_test != 3
|
39
|
+
|
40
|
+
throw "chainable failed test should 2 #{t.get_testside.inspect}" if t.get_testside != 2
|
41
|
+
throw "chainable failed sideeffect should 1 nil #{t.sideeffect.inspect}" if !t.sideeffect.nil?
|
42
|
+
t.testside
|
43
|
+
throw "chainable failed this should be 1 " if t.get_testside != 1
|
44
|
+
throw "chainable failed sideeffect should 2 nil #{t.sideeffect.inspect}" if t.sideeffect != 10
|
45
|
+
t.testside(3)
|
46
|
+
throw "chainable failed" if t.get_testside != 3
|
47
|
+
throw "chainable failed sideeffect should 2 nil #{t.sideeffect.inspect}" if t.sideeffect != 11
|
48
|
+
|
49
|
+
throw "chainable failed true" unless t.testbool? == true
|
50
|
+
t.testbool
|
51
|
+
throw "chainable failed false" unless t.testbool? == false
|
52
|
+
t.testbool(4)
|
53
|
+
throw "chainable failed 4" unless t.testbool? == 4
|
54
|
+
t.testbool
|
55
|
+
throw "chainable failed false" unless t.testbool? == false
|
56
|
+
|
57
|
+
throw "chainable failed 2 true" unless t.testbool2? == true
|
58
|
+
t.testbool2
|
59
|
+
throw "chainable failed 2 false" unless t.testbool2? == true
|
60
|
+
t.testbool2(4)
|
61
|
+
throw "chainable failed 2 4" unless t.testbool2? == 4
|
62
|
+
t.testbool2
|
63
|
+
throw "chainable failed 2 false" unless t.testbool2? == true
|
64
|
+
end
|
65
|
+
a=[Test.new,Test.new,Test.new]
|
66
|
+
a[0].testbool(0)
|
67
|
+
throw "chainable failed 0" unless a[0].testbool? == 0
|
68
|
+
throw "chainable failed 1" unless a[1].testbool? == true
|
69
|
+
a[2].testbool
|
70
|
+
throw "chainable failed 2" unless a[2].testbool? == false
|
71
|
+
|
72
|
+
throw "chainable failed 0" unless a[0].testbool? == 0
|
73
|
+
throw "chainable failed 1" unless a[1].testbool? == true
|
74
|
+
throw "chainable failed 2" unless a[2].testbool? == false
|
75
|
+
end
|
76
|
+
@test = self.test
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Construqt
|
2
|
+
class Users
|
3
|
+
def initialize(region)
|
4
|
+
@region = region
|
5
|
+
@users = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(name, cfg)
|
9
|
+
throw "user exists #{name}" if @users[name]
|
10
|
+
cfg['name'] = name
|
11
|
+
cfg['yubikey'] ||= nil
|
12
|
+
@users[name] = OpenStruct.new(cfg)
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
@users.values
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Construqt
|
2
|
+
module Util
|
3
|
+
module Chainable
|
4
|
+
|
5
|
+
def self.included(other)
|
6
|
+
#puts "Chainable #{other.name}"
|
7
|
+
other.class.send("define_method", "chainable_attr") do |*args|
|
8
|
+
#puts "chainable_attr:#{self.name} #{args.inspect}"
|
9
|
+
Chainable.chainable_attr(self, *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
other.class.send("define_method", "chainable_attr_value") do |*args|
|
13
|
+
#puts "chainable_attr_value:#{self.name} #{args.inspect}"
|
14
|
+
Chainable.chainable_attr_value(self, *args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.chainable_attr_value(clazz, arg, init = nil)
|
19
|
+
instance_variable_name = "@#{arg}".to_sym
|
20
|
+
self.instance_variable_set(instance_variable_name, init)
|
21
|
+
define_method(arg.to_s) do |val|
|
22
|
+
self.instance_variable_set(instance_variable_name, val)
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method("get_#{arg}") do
|
27
|
+
self.instance_variable_get(instance_variable_name.to_sym)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.chainable_attr(clazz, arg, set_value = true, init = false, aspect = lambda{|i|})
|
32
|
+
instance_variable_name = "@#{arg}".to_sym
|
33
|
+
# puts ">>>chainable_attr #{"%x"%self.object_id} init=#{init}"
|
34
|
+
# self.instance_variable_set(instance_variable_name, init)
|
35
|
+
#puts "self.chainable_attr #{clazz.name} #{arg.to_sym} #{set_value} #{init}"
|
36
|
+
clazz.send("define_method", arg.to_sym) do |*args|
|
37
|
+
instance_eval(&aspect)
|
38
|
+
self.instance_variable_set(instance_variable_name, args.length>0 ? args[0] : set_value)
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
if ((set_value.kind_of?(true.class) || set_value.kind_of?(false.class)) &&
|
43
|
+
(init.kind_of?(true.class) || init.kind_of?(false.class)))
|
44
|
+
get_name = "#{arg}?"
|
45
|
+
else
|
46
|
+
get_name = "get_#{arg}"
|
47
|
+
end
|
48
|
+
|
49
|
+
get_name_proc = Proc.new do
|
50
|
+
unless self.instance_variables.include?(instance_variable_name)
|
51
|
+
#puts "init #{get_name} #{instance_variable_name} #{defined?(instance_variable_name)} #{set_value} #{init}"
|
52
|
+
self.instance_variable_set(instance_variable_name, init)
|
53
|
+
end
|
54
|
+
|
55
|
+
ret = self.instance_variable_get(instance_variable_name)
|
56
|
+
#puts "#{self.class.name} #{get_name} #{set_value} #{init} => #{ret.inspect}"
|
57
|
+
ret
|
58
|
+
end
|
59
|
+
|
60
|
+
clazz.send("define_method", get_name, get_name_proc)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.write_str(str, *path)
|
65
|
+
path = File.join("cfgs", *path)
|
66
|
+
FileUtils.mkdir_p(File.dirname(path))
|
67
|
+
File.open(path, 'w') {|f| f.write(str) }
|
68
|
+
Construqt.logger.info "Write:#{path}"
|
69
|
+
return str
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.password(a)
|
73
|
+
a
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.add_gre_prefix(name)
|
77
|
+
unless name.start_with?("gt")
|
78
|
+
return "gt"+name
|
79
|
+
end
|
80
|
+
|
81
|
+
name
|
82
|
+
end
|
83
|
+
|
84
|
+
@clean_if = []
|
85
|
+
def self.add_clean_ip_pattern(pat)
|
86
|
+
@clean_if << pat
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.clean_if(prefix, name)
|
90
|
+
unless name.start_with?(prefix)
|
91
|
+
name = prefix+name
|
92
|
+
end
|
93
|
+
|
94
|
+
name = name.gsub(/[^a-z0-9]/, '')
|
95
|
+
@clean_if.each { |pat| name.gsub!(pat, '') }
|
96
|
+
name
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.clean_bgp(name)
|
100
|
+
name.gsub(/[^a-z0-9]/, '_')
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.portNeighbors?(port1, port2)
|
104
|
+
port2.succ == port1 || port1.succ == port2
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.createRangeDefinition(ports)
|
108
|
+
ranges=[]
|
109
|
+
lastPort=nil
|
110
|
+
|
111
|
+
#remove duplicates
|
112
|
+
ports.uniq.sort do |l,r|
|
113
|
+
fc = l.to_s.length <=> r.to_s.length
|
114
|
+
fc!=0 ? fc : l<=>r
|
115
|
+
end.each do |port|
|
116
|
+
port = port.to_s
|
117
|
+
if (ranges.length>0 && portNeighbors?(port, ranges[ranges.length-1]["to"]))
|
118
|
+
ranges[ranges.length-1]["to"] = port
|
119
|
+
else
|
120
|
+
ranges << {"from" => port, "to" => port}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
ranges = ranges.map do |range|
|
125
|
+
range["from"] == range["to"] ? range["from"] : range["from"] +"-"+range["to"]
|
126
|
+
end
|
127
|
+
#puts "self.createRangeDefinition[#{ports}]=>#{ranges}"
|
128
|
+
ranges.join(",")
|
129
|
+
end
|
130
|
+
|
131
|
+
PORTS_DEF_REGEXP = "([^\\d\\s]*[\\d,-]+)+"
|
132
|
+
PORT_NAME_REGEXP="^(.*?)(\\d+)$"
|
133
|
+
def self.expandRangeDefinition(list_str)
|
134
|
+
ports = list_str.strip.split(",").map do |range_def|
|
135
|
+
range = range_def.split("-")
|
136
|
+
if (range.length==1)
|
137
|
+
range
|
138
|
+
elsif (range.length==2)
|
139
|
+
range[0]=~/#{PORT_NAME_REGEXP}/
|
140
|
+
prefix_from=$1
|
141
|
+
from = $2
|
142
|
+
range[1]=~/#{PORT_NAME_REGEXP}/
|
143
|
+
prefix_to=$1
|
144
|
+
to = $2
|
145
|
+
throw "port prefixes differ" unless prefix_from==prefix_to
|
146
|
+
(from.to_i .. to.to_i).map {|n| prefix_from + n.to_s }
|
147
|
+
else
|
148
|
+
throw "invalid range found #{range_def}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
ports.flatten
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.generate_mac_address_from_name(name)
|
155
|
+
# http://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml
|
156
|
+
'8f:'+Digest::SHA256.hexdigest("#{name}").scan(/../)[0,5].join(':')
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.indent(body, ident)
|
160
|
+
body.lines.map { |line| ident+line }.join("\n")
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
module Construqt
|
3
|
+
class Vlans
|
4
|
+
def initialize(region)
|
5
|
+
@region = region
|
6
|
+
@vlans_id = {}
|
7
|
+
@vlans_description = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
class Vlan < OpenStruct
|
11
|
+
def initialize(cfg)
|
12
|
+
super(cfg)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tagged?
|
16
|
+
@tagged
|
17
|
+
end
|
18
|
+
|
19
|
+
def tagged
|
20
|
+
@tagged=true
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def untagged?
|
25
|
+
!@tagged
|
26
|
+
end
|
27
|
+
|
28
|
+
def untagged
|
29
|
+
@tagged = false
|
30
|
+
self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def add(vlan, cfg)
|
35
|
+
throw "vlan has to be a fixnum #{vlan}" unless vlan.kind_of?(Fixnum)
|
36
|
+
throw "vlan need #{vlan} description" unless cfg['description']
|
37
|
+
throw "vlan with id #{vlan} exists" if @vlans_id[vlan]
|
38
|
+
throw "vlan with description #{vlan} exists" if @vlans_description[cfg['description']]
|
39
|
+
cfg['vlan_id'] = vlan
|
40
|
+
ret = Vlan.new(cfg)
|
41
|
+
@vlans_id[vlan] = ret
|
42
|
+
@vlans_description[cfg['description']] = ret
|
43
|
+
ret
|
44
|
+
end
|
45
|
+
|
46
|
+
def clone(key)
|
47
|
+
throw "vlan clone key not found #{key}" unless @vlans_id[key] || @vlans_description[key]
|
48
|
+
(@vlans_id[key] || @vlans_description[key]).clone
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/construqt.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
require 'ipaddress'
|
7
|
+
require 'digest/sha1'
|
8
|
+
require 'digest/md5'
|
9
|
+
require "base64"
|
10
|
+
require 'securerandom'
|
11
|
+
|
12
|
+
|
13
|
+
module Construqt
|
14
|
+
|
15
|
+
@logger = Logger.new(STDOUT)
|
16
|
+
@logger.level = Logger::DEBUG
|
17
|
+
|
18
|
+
def self.log_level(level)
|
19
|
+
@logger.level = level
|
20
|
+
end
|
21
|
+
|
22
|
+
if !IPAddress::IPv6.instance_methods.include?(:rev_domains)
|
23
|
+
@logger.fatal "you need the right ipaddress version from https://github.com/mabels/ipaddress"
|
24
|
+
end
|
25
|
+
|
26
|
+
if !OpenStruct.instance_methods.include?(:to_h)
|
27
|
+
OpenStruct.class_eval do
|
28
|
+
def to_h
|
29
|
+
@table.dup
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@logger.warn "Your running a patched version of OpenStruct"
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.logger
|
37
|
+
@logger
|
38
|
+
end
|
39
|
+
|
40
|
+
# ugly but i need the logger during initialization
|
41
|
+
require_relative 'construqt/util.rb'
|
42
|
+
require_relative 'construqt/services.rb'
|
43
|
+
require_relative 'construqt/networks.rb'
|
44
|
+
require_relative 'construqt/addresses.rb'
|
45
|
+
require_relative 'construqt/bgps.rb'
|
46
|
+
require_relative 'construqt/users.rb'
|
47
|
+
require_relative 'construqt/firewalls.rb'
|
48
|
+
require_relative 'construqt/flavour/delegates.rb'
|
49
|
+
require_relative 'construqt/resource.rb'
|
50
|
+
require_relative 'construqt/hostid.rb'
|
51
|
+
require_relative 'construqt/hosts.rb'
|
52
|
+
require_relative 'construqt/interfaces.rb'
|
53
|
+
require_relative 'construqt/cables.rb'
|
54
|
+
require_relative 'construqt/ipsecs.rb'
|
55
|
+
require_relative 'construqt/firewalls.rb'
|
56
|
+
require_relative 'construqt/templates.rb'
|
57
|
+
require_relative 'construqt/regions.rb'
|
58
|
+
require_relative 'construqt/vlans.rb'
|
59
|
+
require_relative 'construqt/tags.rb'
|
60
|
+
require_relative 'construqt/flavour/flavour.rb'
|
61
|
+
|
62
|
+
require_relative 'construqt/flavour/unknown/unknown.rb'
|
63
|
+
[
|
64
|
+
'construqt/flavour/ciscian/ciscian.rb',
|
65
|
+
'construqt/flavour/plantuml/plantuml.rb',
|
66
|
+
'construqt/flavour/mikrotik/flavour_mikrotik.rb',
|
67
|
+
'construqt/flavour/ubuntu/flavour_ubuntu.rb'].each do |fname|
|
68
|
+
begin
|
69
|
+
require_relative fname
|
70
|
+
rescue LoadError
|
71
|
+
Construqt::logger.warn("can not load driver:#{fname}")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.produce(region_or_hosts)
|
76
|
+
hosts = false
|
77
|
+
hosts = region_or_hosts if region_or_hosts.kind_of?(Array)
|
78
|
+
hosts = region_or_hosts.hosts.get_hosts if region_or_hosts.kind_of?(Construqt::Regions::Region)
|
79
|
+
throw "need a region or hosts list" unless hosts
|
80
|
+
Construqt::Ipsecs.build_config()
|
81
|
+
Construqt::Bgps.build_config()
|
82
|
+
hosts.inject({}) do |r, host|
|
83
|
+
r[host.region.name] ||= []
|
84
|
+
r[host.region.name] << host
|
85
|
+
r
|
86
|
+
end.values.each do |hosts|
|
87
|
+
hosts.first.region.hosts.build_config(hosts)
|
88
|
+
hosts.first.region.interfaces.build_config(hosts)
|
89
|
+
hosts.first.region.hosts.commit(hosts)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|