Class: OsCtld::NetConfig

Inherits:
Object
  • Object
show all
Defined in:
lib/osctld/net_config.rb

Overview

Generate network configuration for a container and apply using netlink

NetConfig has to be created before switching to container user and attaching to the container. Call NetConfig.create while running as root and #setup while attached into a container.

Defined Under Namespace

Classes: Addr, NetIf, Route

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNetConfig

Returns a new instance of NetConfig.



32
33
34
# File 'lib/osctld/net_config.rb', line 32

def initialize
  @netifs = []
end

Instance Attribute Details

#netifsObject (readonly)

Returns the value of attribute netifs.



17
18
19
# File 'lib/osctld/net_config.rb', line 17

def netifs
  @netifs
end

Class Method Details

.create(ct) ⇒ Object

Parameters:



20
21
22
23
24
# File 'lib/osctld/net_config.rb', line 20

def self.create(ct)
  cfg = new
  ct.netifs.each { |netif| cfg.add_netif(netif) }
  cfg
end

.import(data) ⇒ Object



26
27
28
29
30
# File 'lib/osctld/net_config.rb', line 26

def self.import(data)
  cfg = new
  cfg.import(data)
  cfg
end

Instance Method Details

#add_netif(netif) ⇒ Object

Parameters:



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/osctld/net_config.rb', line 37

def add_netif(netif)
  n = NetIf.new(netif.name, [], [])

  [4, 6].each do |ip_v|
    if netif.respond_to?(:ips)
      netif.ips(ip_v).each do |ip|
        n.ips << Addr.new(ip_v, ip.to_s, ip.prefix.to_i)
      end
    end

    case netif.type
    when :bridge
      if netif.has_gateway?(ip_v)
        n.routes << Route.new(ip_v, '0.0.0.0', 0, netif.gateway(ip_v))
      end

    when :routed
      begin
        via = netif.default_via(ip_v).to_s
        n.routes << Route.new(ip_v, via, ip_v == 4 ? 32 : 128, nil)
        n.routes << Route.new(ip_v, '0.0.0.0', 0, via)

      rescue RuntimeError
        # IPv6 is routed via link-local address on the host interface, which
        # is not known when the container is stopped.
        next if ip_v == 6
      end
    end
  end

  netifs << n
end

#exportObject



98
99
100
101
102
103
104
105
106
# File 'lib/osctld/net_config.rb', line 98

def export
  netifs.map do |netif|
    {
      name: netif.name,
      ips: netif.ips.map(&:to_h),
      routes: netif.routes.map(&:to_h),
    }
  end
end

#import(data) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/osctld/net_config.rb', line 108

def import(data)
  data.each do |netif_hash|
    netifs << NetIf.new(
      netif_hash[:name],

      netif_hash[:ips].map do |v|
        Addr.new(v[:version], v[:address], v[:prefix])
      end,

      netif_hash[:routes].map do |v|
        Route.new(v[:version], v[:address], v[:prefix], v[:via])
      end,
    )
  end
end

#setupObject

Apply configuration using netlink



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/osctld/net_config.rb', line 71

def setup
  nl = Linux::Netlink::Route::Socket.new

  netifs.each do |netif|
    netif.ips.each do |ip|
      begin
        nl.addr.add(index: netif.name, local: ip.address, prefixlen: ip.prefix)
      rescue Errno::EEXIST
        next
      end
    end

    netif.routes.each do |route|
      begin
        nl.route.add(
          oif: netif.name,
          dst: route.address,
          dst_len: route.prefix,
          gateway: route.via,
        )
      rescue Errno::EEXIST
        next
      end
    end
  end
end