Files
puppet-vswitch/lib/puppet/provider/vs_port/ovs.rb
Benedikt Trefzer 081e9be22b fix vs_port interface_type
if setting interface_type equal 'internal' requires
a different ovs-vsctl call to create the port.

Closes-Bug: #1771134
Change-Id: Ib56b424b85a1be5ab34fc1e3255c017081509f0d
2025-04-20 17:01:25 +02:00

165 lines
4.5 KiB
Ruby

require File.join(File.dirname(__FILE__), '..','..','..', 'puppet/provider/ovs')
Puppet::Type.type(:vs_port).provide(
:ovs,
:parent => Puppet::Provider::Ovs
) do
UUID_RE ||= /[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}/
commands :vsctl => 'ovs-vsctl'
has_feature :bonding
has_feature :vlan
has_feature :interface_type
def exists?
vsctl('list-ports', @resource[:bridge]).split("\n").include? @resource[:port]
rescue Puppet::ExecutionFailure => e
return false
end
def create
if ! bridge.exists?
raise Puppet::Error, "Bridge #{@resource[:bridge]} does not exist"
end
# create with first interface, other interfaces will be added later when synchronizing properties
if @resource[:interface_type] == :internal
vsctl('add-port', @resource[:bridge], @resource[:port], '--', 'set', 'Interface', @resource[:port], 'type=internal')
else
vsctl('--', '--id=@iface0', 'create', 'Interface', "name=#{@resource[:interface][0]}", '--', 'add-port', @resource[:bridge], @resource[:port], 'interfaces=@iface0')
end
# synchronize properties
# Only sync those properties actually supported by the provider. This
# allows this provider to be used as a base class for providers not
# supporting all properties.
sync_properties = []
if @resource.provider.class.feature?(:bonding)
sync_properties += [:interface,
:bond_mode,
:lacp,
:lacp_time,
]
end
if @resource.provider.class.feature?(:vlan)
sync_properties += [:vlan_mode,
:vlan_tag,
:vlan_trunks,
]
end
if @resource.provider.class.feature?(:interface_type)
sync_properties += [:interface_type,
]
end
for prop_name in sync_properties
property = @resource.property(prop_name)
property.sync unless property.safe_insync?(property.retrieve)
end
end
def destroy
vsctl('del-port', @resource[:bridge], @resource[:port])
end
def interface
get_port_interface_property('name')
end
def interface=(value)
# find interfaces we want to keep on the port
keep = @resource.property(:interface).retrieve() & value
keep_uids = keep.map { |iface| vsctl('get', 'Interface', iface, '_uuid').strip }
new = value - keep
args = ['--'] + new.each_with_index.map { |iface, i| ["--id=@#{i+1}", 'create', 'Interface', "name=#{iface}", '--'] }
ifaces = (1..new.length).map { |i| "@#{i}" } + keep_uids
args += ['set', 'Port', @resource[:port], "interfaces=#{ifaces.join(',')}"]
vsctl(*args)
end
def interface_type
types = get_port_interface_property('type').uniq
types != nil ? types.join(' ') : :system
end
def interface_type=(value)
@resource.property(:interface).retrieve.each do |iface|
vsctl('set', 'Interface', iface, "type=#{value}")
end
end
def bond_mode
get_port_property('bond_mode')
end
def bond_mode=(value)
set_port_property('bond_mode', value)
end
def lacp
get_port_property('lacp')
end
def lacp=(value)
set_port_property('lacp', value)
end
def lacp_time
val = self.class.get_other_config('Port', @resource[:port], 'lacp-time')
if val.nil? then '' else val.gsub(/^"|"$/, '') end
end
def lacp_time=(value)
self.class.set_other_config('Port', @resource[:port], 'lacp-time', value)
end
def vlan_mode
get_port_property('vlan_mode')
end
def vlan_mode=(value)
set_port_property('vlan_mode', value)
end
def vlan_tag
get_port_property('tag')
end
def vlan_tag=(value)
set_port_property('tag', value)
end
def vlan_trunks
get_port_property('trunks').scan(/\d+/)
end
def vlan_trunks=(value)
set_port_property('trunks', value.join(' '))
end
protected
def bridge
@bridge ||= Puppet::Type.type(:vs_bridge).provider(:ovs).new(
Puppet::Type::Vs_bridge.new(:title => @resource[:bridge])
)
end
private
def get_port_property(key)
value = self.class.get_property('Port', @resource[:port], key)
if value == '[]' then '' else value end
end
def set_port_property(key, value)
self.class.set_property('Port', @resource[:port], key, value)
end
def get_port_interface_property(key)
uuids = get_port_property('interfaces').scan(UUID_RE)
uuids.map!{|id| self.class.get_property('Interface', id, key).gsub(/^"|"$/, '')}
end
end