Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions features/dsl/netns.feature
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,21 @@ Feature: The netns DSL directive.
And the netns "host2" have the following route:
| net | gateway |
| 0.0.0.0 | 192.168.1.254 |

@sudo
Scenario: vlan option
Given a file named "phut.conf" with:
"""
netns('host1') {
ip '192.168.0.1'
vlan 10
}
netns('host2') {
ip '192.168.1.2'
vlan 20
}
link 'host1', 'host2'
"""
When I do phut run "phut.conf"
Then the VLAN of the netns "host1" should be "10"
And the VLAN of the netns "host2" should be "20"
4 changes: 4 additions & 0 deletions features/step_definitions/netns_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@
expect(netns.route.net).to eq table.hashes.first['net']
expect(netns.route.gateway).to eq table.hashes.first['gateway']
end

Then(/^the VLAN of the netns "([^"]*)" should be "([^"]*)"$/) do |name, vlan|
expect(Phut::Netns.find_by!(name: name).vlan).to eq vlan
end
60 changes: 43 additions & 17 deletions lib/phut/netns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'phut/finder'
require 'phut/route'
require 'phut/shell_runner'
require 'phut/veth'

module Phut
# `ip netns ...` command runner
Expand All @@ -14,7 +15,7 @@ class Netns
def self.all
sh('ip netns list').split("\n").map do |each|
name = each.split.first
addr_list = sudo("ip -netns #{name} -4 -o addr list").split("\n")
addr_list = sudo("ip netns exec #{name} ip -4 -o addr list").split("\n")
if addr_list.size > 1
%r{inet ([^/]+)/(\d+)} =~ addr_list[1]
new(name: name,
Expand Down Expand Up @@ -43,45 +44,70 @@ def self.destroy_all
attr_reader :ip_address

def initialize(name:,
ip_address: nil, netmask: '255.255.255.255', route: {})
ip_address: nil, netmask: '255.255.255.255',
route: {}, vlan: nil)
@name = name
@ip_address = ip_address
@netmask = netmask
@route = Route.new(net: route[:net], gateway: route[:gateway])
@vlan = vlan
end

def run
sudo "ip netns add #{@name}"
sudo "ip netns exec #{@name} ifconfig lo 127.0.0.1"
sudo "ip netns add #{name}"
sudo "ip netns exec #{name} ifconfig lo 127.0.0.1"
end

def netmask
if %r{inet [^/]+/(\d+) } =~
sudo("ip -netns #{@name} -o -4 address show dev #{device}")
IPAddr.new('255.255.255.255').mask(Regexp.last_match(1).to_i).to_s
end
def stop
sudo "ip netns delete #{name}"
end

def device
if /^\d+: ([^@]+)@/ =~ sudo("ip -netns #{@name} -o link show type veth")
if /^\d+: (#{Phut::Veth::PREFIX}[^:\.]*?)[:@]/ =~
sudo("ip netns exec #{name} ip -o link show")
Regexp.last_match(1)
end
end

# rubocop:disable MethodLength
def device=(device_name)
return unless device_name
sudo "ip link set dev #{device_name} netns #{@name}"
sudo "ip netns exec #{@name} "\
"ifconfig #{device_name} #{@ip_address} netmask #{@netmask}"
@route.add @name
sudo "ip link set dev #{device_name} netns #{name}"

vlan_suffix = @vlan ? ".#{@vlan}" : ''
if @vlan
sudo "ip netns exec #{name} ip link set #{device_name} up"
sudo "ip netns exec #{name} "\
"ip link add link #{device_name} name "\
"#{device_name}#{vlan_suffix} type vlan id #{@vlan}"
end
sudo "ip netns exec #{name} ip link set #{device_name}#{vlan_suffix} up"
sudo "ip netns exec #{name} "\
"ip addr replace #{@ip_address}/#{@netmask} "\
"dev #{device_name}#{vlan_suffix}"

sudo "ip netns exec #{name} ip link set #{device_name}#{vlan_suffix} up"

@route.add name
end
# rubocop:enable MethodLength

def stop
sudo "ip netns delete #{@name}"
def netmask
if %r{inet [^/]+/(\d+) } =~
sudo("ip netns exec #{name} ip -o -4 address show dev #{device}")
IPAddr.new('255.255.255.255').mask(Regexp.last_match(1).to_i).to_s
end
end

def route
Route.read @name
Route.read name
end

def vlan
if /^\d+: #{device}\.(\d+)@/ =~
sudo("ip netns exec #{name} ip -o link show")
Regexp.last_match(1)
end
end
end
end
3 changes: 2 additions & 1 deletion lib/phut/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ def update_netns_interfaces
netns =
Netns.create(name: each[:name],
ip_address: each[:ip], netmask: each[:netmask],
route: { net: each[:net], gateway: each[:gateway] })
route: { net: each[:net], gateway: each[:gateway] },
vlan: each[:vlan])
netns.device = find_network_device(each.name)
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/phut/syntax/netns_directive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def route(options)
@attributes[:net] = options.fetch(:net)
@attributes[:gateway] = options.fetch(:gateway)
end

def vlan(value)
@attributes[:vlan] = value
end
end
end
end
4 changes: 2 additions & 2 deletions lib/phut/veth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class Veth

def self.all
Netns.all.map(&:device).compact +
sh('ip -o link show type veth').split("\n").map do |each|
/^\d+: (#{PREFIX}\d+_[^@]+)@/ =~ each ? Regexp.last_match(1) : nil
sh('ip -o link show').split("\n").map do |each|
/^\d+: (#{PREFIX}\d+_[^:]*?)[@:]/ =~ each ? Regexp.last_match(1) : nil
end.compact
end

Expand Down