Added custom type vs_config and OVS provider for it
vs_config checks and updates the columns in Open_vSwitch table. Records are updated only when the value differs from the one set in 'value' parameter. This will be used by projects like OVN which depends on the global configs to even boot up Change-Id: I87f870463147b41a319f1fc6c4225c35d244e3b9
This commit is contained in:
parent
3ebeb07188
commit
7d1ff4325e
33
README.md
33
README.md
@ -12,6 +12,7 @@ The current layout is:
|
||||
|
||||
* bridges - A "Bridge" is basically the thing you plug ports / interfaces into.
|
||||
* ports - A Port is a interface you plug into the bridge (switch).
|
||||
* configs - Configuration settings, if any
|
||||
|
||||
## USAGE:
|
||||
To create a new bridge, use the `vs_bridge` type:
|
||||
@ -30,6 +31,38 @@ vs_port { 'eth2':
|
||||
}
|
||||
```
|
||||
|
||||
You can change the vswitch configuration settings using.
|
||||
```
|
||||
vs_config { 'parameter_name':
|
||||
ensure => present,
|
||||
value => "some_value"
|
||||
}
|
||||
```
|
||||
For configuration parameters that are 'hash' data type, the resource name
|
||||
should be of the following format
|
||||
|
||||
```
|
||||
parameter-name:key-name
|
||||
|
||||
Ex.
|
||||
vs_config { 'external_ids:ovn-remote':
|
||||
ensure => present,
|
||||
value => 'tcp:127.0.0.1:6640'
|
||||
}
|
||||
```
|
||||
|
||||
For 'set/array' data types, value should be in the following format
|
||||
|
||||
```
|
||||
'[<values>]'
|
||||
|
||||
Ex.
|
||||
vs_config { 'array_key':
|
||||
ensure => present,
|
||||
value => '[2, 1, 6, 4]'
|
||||
}
|
||||
```
|
||||
|
||||
## Beaker-Rspec
|
||||
|
||||
This module has beaker-rspec tests
|
||||
|
107
lib/puppet/provider/vs_config/ovs.rb
Normal file
107
lib/puppet/provider/vs_config/ovs.rb
Normal file
@ -0,0 +1,107 @@
|
||||
require 'puppet'
|
||||
|
||||
Puppet::Type.type(:vs_config).provide(:ovs) do
|
||||
|
||||
commands :vsctl => 'ovs-vsctl'
|
||||
|
||||
mk_resource_methods
|
||||
|
||||
def self.munge_array_value(value)
|
||||
"[#{value[1..-2].split(',').map(&:strip).sort.join(",")}]"
|
||||
end
|
||||
|
||||
def self.parse_column_value(value)
|
||||
value = value.chomp
|
||||
if value[0] == '{'
|
||||
# hash case, like {system-id=\"some-id\", name=\"some-name\"}
|
||||
type = 'hash'
|
||||
res = {}
|
||||
value[1..-2].gsub('"','').split(', ').map(&:strip).each do |v|
|
||||
k,val = v.split("=")
|
||||
res[k] = val
|
||||
end
|
||||
elsif value[0] == '['
|
||||
# set case, like ['id1', 'id2', 'id3']
|
||||
type = 'set'
|
||||
res = munge_array_value(value)
|
||||
else
|
||||
# simple string
|
||||
type = 'string'
|
||||
res = value
|
||||
end
|
||||
|
||||
{
|
||||
:type => type,
|
||||
:value => res
|
||||
}
|
||||
end
|
||||
|
||||
def self.list_config_entries
|
||||
open_vs = vsctl("list", "Open_vSwitch", ".").split("\n")
|
||||
configs = []
|
||||
open_vs.each do |line|
|
||||
key, value = line.split(' : ').map(&:strip)
|
||||
parsed_value = parse_column_value(value)
|
||||
if parsed_value[:type] == "hash"
|
||||
parsed_value[:value].each do |k, v|
|
||||
configs.push({
|
||||
:name => "#{key}:#{k}",
|
||||
:value => v,
|
||||
:ensure => :present
|
||||
})
|
||||
end
|
||||
else
|
||||
configs.push({
|
||||
:name => key,
|
||||
:ensure => :present,
|
||||
:value => parsed_value[:value],
|
||||
})
|
||||
end
|
||||
end
|
||||
configs
|
||||
end
|
||||
|
||||
def self.instances()
|
||||
configs = list_config_entries
|
||||
configs.collect do |config|
|
||||
new(config)
|
||||
end
|
||||
end
|
||||
|
||||
def self.prefetch(resources)
|
||||
instances.each do |prov|
|
||||
if resource = resources[prov.name]
|
||||
resource.provider = prov
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(value)
|
||||
super(value)
|
||||
end
|
||||
|
||||
def exists?
|
||||
@property_hash[:ensure] == :present
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @resource[:name].include?(':')
|
||||
name, key = @resource[:name].split(':')
|
||||
vsctl("remove", "Open_vSwitch", ".", name, key)
|
||||
else
|
||||
vsctl("clear", "Open_vSwitch", ".", @resource[:name])
|
||||
end
|
||||
end
|
||||
|
||||
def _set
|
||||
vsctl("set", "Open_vSwitch", ".", "#{@resource[:name]}=#{@resource[:value]}")
|
||||
end
|
||||
|
||||
def create
|
||||
_set
|
||||
end
|
||||
|
||||
def value=(value)
|
||||
_set
|
||||
end
|
||||
end
|
36
lib/puppet/type/vs_config.rb
Normal file
36
lib/puppet/type/vs_config.rb
Normal file
@ -0,0 +1,36 @@
|
||||
require 'puppet'
|
||||
|
||||
Puppet::Type.newtype(:vs_config) do
|
||||
desc 'Switch configurations'
|
||||
|
||||
ensurable
|
||||
|
||||
newparam(:name, :namevar => true) do
|
||||
desc 'Configuration parameter whose value need to be set'
|
||||
|
||||
validate do |value|
|
||||
if !value.is_a?(String)
|
||||
raise ArgumentError, "Invalid name #{value}. Requires a String, not a #{value.class}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
newproperty(:value) do
|
||||
desc 'Configuration value for the paramter'
|
||||
|
||||
validate do |value|
|
||||
if !value.is_a?(String)
|
||||
raise ArgumentError, "Invalid external_ids #{value}. Requires a String, not a #{value.class}"
|
||||
end
|
||||
end
|
||||
|
||||
munge do |value|
|
||||
if value[0] == '[' && value[-1] == ']'
|
||||
"[#{value[1..-2].split(',').map(&:strip).sort.join(",")}]"
|
||||
else
|
||||
super(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -14,6 +14,11 @@ describe 'basic vswitch' do
|
||||
vs_bridge { 'br-beaker':
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
vs_config { 'external_ids:ovn-remote':
|
||||
ensure => present,
|
||||
value => 'tcp:127.0.0.1:2300',
|
||||
}
|
||||
EOS
|
||||
|
||||
|
||||
@ -28,5 +33,12 @@ describe 'basic vswitch' do
|
||||
it { is_expected.to match /br-beaker/ }
|
||||
end
|
||||
end
|
||||
|
||||
describe command('ovs-vsctl get Open_vSwitch . external_ids:ovn-remote') do
|
||||
describe '#stdout' do
|
||||
subject { super().stdout }
|
||||
it { is_expected.to match /\"tcp:127.0.0.1:2300\"/ }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
98
spec/unit/puppet/lib/provider/vs_config_ovs_spec.rb
Normal file
98
spec/unit/puppet/lib/provider/vs_config_ovs_spec.rb
Normal file
@ -0,0 +1,98 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Puppet::Type.type(:vs_config).provider(:ovs) do
|
||||
it 'should have an instance method' do
|
||||
expect(described_class).to respond_to :instances
|
||||
end
|
||||
|
||||
it 'should have a prefetch method' do
|
||||
expect(described_class).to respond_to :prefetch
|
||||
end
|
||||
|
||||
context "Testing string values" do
|
||||
before :each do
|
||||
described_class.expects(:vsctl).with(
|
||||
"list", "Open_vSwitch", ".").returns 'key1 : value1
|
||||
key2 : value2
|
||||
key3 : value3'
|
||||
end
|
||||
|
||||
it "should return three resources" do
|
||||
expect(described_class.instances.size).to eq(3)
|
||||
end
|
||||
|
||||
it "should return the appropriate property hash" do
|
||||
described_class.instances.each do |inst|
|
||||
_inst = inst.instance_variable_get("@property_hash")
|
||||
expect(_inst.key?(:name)).to eq true
|
||||
expect(_inst.key?(:value)).to eq true
|
||||
expect(_inst.key?(:ensure)).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
it "should contain proper values" do
|
||||
described_class.instances.each do |inst|
|
||||
_inst = inst.instance_variable_get("@property_hash")
|
||||
expect(_inst[:name][0..2]).to eq "key"
|
||||
expect(_inst[:value][0..4]).to eq "value"
|
||||
expect(_inst[:value][5]).to eq _inst[:name][3]
|
||||
expect(_inst[:ensure]).to eq :present
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Testing array values" do
|
||||
before :each do
|
||||
described_class.expects(:vsctl).with(
|
||||
"list", "Open_vSwitch", ".").returns 'key1 : [abc, def, ghi]
|
||||
key2 : [def, abc, ghi]
|
||||
key3 : [1001, 399, 240, 1200]'
|
||||
end
|
||||
|
||||
it "should return three resources" do
|
||||
expect(described_class.instances.size).to eq(3)
|
||||
end
|
||||
|
||||
it "should contain proper values" do
|
||||
expected_values = {
|
||||
"key1" => "[abc,def,ghi]",
|
||||
"key2" => "[abc,def,ghi]",
|
||||
"key3" => "[1001,1200,240,399]"
|
||||
}
|
||||
described_class.instances.each do |inst|
|
||||
_inst = inst.instance_variable_get("@property_hash")
|
||||
expect(expected_values.key?(_inst[:name])).to eq true
|
||||
expect(_inst[:value]).to eq expected_values[_inst[:name]]
|
||||
expect(_inst[:ensure]).to eq :present
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Testing hash values" do
|
||||
before :each do
|
||||
described_class.expects(:vsctl).with(
|
||||
"list", "Open_vSwitch", ".").returns 'key1 : {}
|
||||
key2 : {"hash21"="value21"}
|
||||
key3 : {"hash31"="value31", "hash32"="value32", "hash33"=33}'
|
||||
end
|
||||
|
||||
it "should return three resources" do
|
||||
expect(described_class.instances.size).to eq(4)
|
||||
end
|
||||
|
||||
it "should contain valid names and values" do
|
||||
expected_values = {
|
||||
"key2:hash21" => "value21",
|
||||
"key3:hash31" => "value31",
|
||||
"key3:hash32" => "value32",
|
||||
"key3:hash33" => "33"}
|
||||
described_class.instances.each do |inst|
|
||||
_inst = inst.instance_variable_get("@property_hash")
|
||||
expect(expected_values.key?(_inst[:name])).to eq true
|
||||
expect(_inst[:value]).to eq expected_values[_inst[:name]]
|
||||
expect(_inst[:ensure]).to eq :present
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
31
spec/unit/puppet/lib/type/vs_config_spec.rb
Normal file
31
spec/unit/puppet/lib/type/vs_config_spec.rb
Normal file
@ -0,0 +1,31 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Puppet::Type.type(:vs_config) do
|
||||
it "should support present as a value for ensure" do
|
||||
expect do
|
||||
described_class.new(:name => 'foo', :ensure => :present)
|
||||
end.to_not raise_error
|
||||
end
|
||||
|
||||
it "should support absent as a value for ensure" do
|
||||
expect do
|
||||
described_class.new(:name => 'foo', :ensure => :absent)
|
||||
end.to_not raise_error
|
||||
end
|
||||
|
||||
it "should have a :value parameter" do
|
||||
expect(described_class.attrtype(:value)).to eq(:property)
|
||||
end
|
||||
|
||||
it "should accept only string values" do
|
||||
expect do
|
||||
described_class.new({:name => "foo", :value => 123, :ensure => :present})
|
||||
end.to raise_error(Puppet::Error)
|
||||
end
|
||||
|
||||
it "should munge array values" do
|
||||
expect(
|
||||
described_class.new({:name => "foo", :value => "[2, 1, 3, 0]", :ensure => :present})[:value]
|
||||
).to eq "[0,1,2,3]"
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user