Skip to content
This repository has been archived by the owner on Jun 5, 2020. It is now read-only.

Commit

Permalink
Merge pull request #120 from dblessing/selfip
Browse files Browse the repository at this point in the history
Support Self IP and VLAN
  • Loading branch information
Ashley Penney committed Jul 23, 2014
2 parents 98341ed + 2f3c155 commit 4cc4547
Show file tree
Hide file tree
Showing 5 changed files with 386 additions and 0 deletions.
126 changes: 126 additions & 0 deletions lib/puppet/provider/f5_selfip/f5_selfip.rb
@@ -0,0 +1,126 @@
require 'puppet/provider/f5'

Puppet::Type.type(:f5_selfip).provide(:f5_selfip, :parent => Puppet::Provider::F5) do
@doc = 'Manage F5 self IPs.'

confine :feature => :posix
defaultfor :feature => :posix

def self.wsdl
'Networking.SelfIPV2'
end

def wsdl
self.class.wsdl
end

def self.instances
instances = []
get_list.each do |selfip|
instances << new(name: selfip, ensure: :present)
end
instances
end

def self.prefetch(resources)
selfips = instances
resources.keys.each do |name|
if provider = selfips.find { |selfip| selfip.name == name }
resources[name].provider = provider

end
end
end

def destroy
message = { routes: { item: resource[:name] }}
transport[wsdl].call(:delete_self_ip, message: message)

@property_hash[:ensure] = :absent
end

def create
message = {
self_ips: { item: resource[:name] },
vlan_names: { item: resource[:vlan] },
addresses: { item: resource[:address] },
netmasks: { item: resource[:netmask] },
traffic_groups: { item: resource[:traffic_group] },
floating_states: { item: resource[:floating_state] }
}
transport[wsdl].call(:create, message: message)
end

def exists?
@property_hash[:ensure] == :present
end

def address
message = { self_ips: { item: self.name } }
transport[wsdl].get(:get_address, message)
end

# Unfortunately you can't change the address.
def address=(value)
Puppet.debug('Cannot change this value, destroying and recreating.')
destroy
create
end

def floating_state
message = { self_ips: { item: self.name } }
transport[wsdl].get(:get_floating_state, message)
end

def floating_state=(value)
message = {
self_ips: { item: self.name },
states: { item: resource[:floating_state] },
}
transport[wsdl].call(:set_floating_states, message: message)
end

def netmask
message = { self_ips: { item: self.name }}
transport[wsdl].get(:get_netmask, message)
end

# Unfortunately you can't change the netmask either.
def netmask=(value)
Puppet.debug('Cannot change this value, destroying and recreating.')
destroy
create
end

def traffic_group
message = { self_ips: { item: self.name }}
transport[wsdl].get(:get_traffic_group, message)
end

def traffic_group=(value)
message = {
self_ips: { item: self.name },
traffic_groups: { item: resource[:traffic_group] },
}
transport[wsdl].call(:set_traffic_group, message: message)
end

def vlan
message = { self_ips: { item: self.name }}
transport[wsdl].get(:get_vlan, message)
end

def vlan=(value)
message = {
self_ips: { item: self.name },
vlan_names: { item: resource[:vlan] },
}
transport[wsdl].call(:set_vlan, message: message)
end

# Obtain a list of static routes.
def self.get_list
response = transport[wsdl].get(:get_list)
return Array(response)
end
end
116 changes: 116 additions & 0 deletions lib/puppet/provider/f5_vlan/f5_vlan.rb
@@ -0,0 +1,116 @@
require 'puppet/provider/f5'

Puppet::Type.type(:f5_vlan).provide(:f5_vlan, :parent => Puppet::Provider::F5) do
@doc = 'Manage F5 VLANs.'

confine :feature => :posix
defaultfor :feature => :posix

def self.wsdl
'Networking.VLAN'
end

def wsdl
self.class.wsdl
end

def self.instances
instances = []
get_list.each do |vlan|
instances << new(name: vlan, ensure: :present)
end
instances
end

def self.prefetch(resources)
vlans = instances
resources.keys.each do |name|
if provider = vlans.find { |vlan| vlan.name == name }
resources[name].provider = provider

end
end
end

def destroy
message = { vlans: { item: resource[:name] }}
transport[wsdl].call(:delete_vlan, message: message)

@property_hash[:ensure] = :absent
end

def create
members = Array.new(1) { Array.new(resource[:members].length) }
members[0] = resource[:members]
message = {
vlans: { item: resource[:name] },
vlan_ids: { item: resource[:vlan_id] },
members: { item: members },
failsafe_states: { item: resource[:failsafe_state] },
timeouts: { item: resource[:timeout] },
}
transport[wsdl].call(:create_v2, message: message)
end

def exists?
@property_hash[:ensure] == :present
end

def failsafe_state
message = { vlans: { item: self.name } }
transport[wsdl].get(:get_failsafe_state, message)
end

def failsafe_state=(value)
message = {
vlans: { item: self.name },
states: { item: resource[:failsafe_state] },
}
transport[wsdl].call(:set_failsafe_state, message: message)
end

def members
message = { vlans: { item: self.name }}
response = transport[wsdl].get(:get_member, message)
return response.is_a?(Array) ? response : Array.new(1) { response }
end

# Unfortunately you can't change the members.
def members=(value)
Puppet.debug('Cannot change this value, destroying and recreating.')
destroy
create
end

def timeout
message = { vlans: { item: self.name } }
transport[wsdl].get(:get_failsafe_timeout, message)
end

def timeout=(value)
message = {
vlans: { item: self.name },
timeouts: { item: resource[:timeouts] },
}
transport[wsdl].call(:set_failsafe_timeout, message: message)
end

def vlan_id
message = { vlans: { item: self.name }}
transport[wsdl].get(:get_vlan_id, message)
end

def vlan_id=(value)
message = {
vlans: { item: self.name },
vlan_ids: { item: resource[:vlan_id] },
}
transport[wsdl].call(:set_vlan_id, message: message)
end

# Obtain a list of static routes.
def self.get_list
response = transport[wsdl].get(:get_list)
return Array(response)
end
end
57 changes: 57 additions & 0 deletions lib/puppet/type/f5_selfip.rb
@@ -0,0 +1,57 @@
require 'ipaddr' # For validation.

Puppet::Type.newtype(:f5_selfip) do
@doc = 'Manage self IPs within the F5.'

apply_to_device
ensurable

VALID_PARTITION = /^\/.*\//

newparam(:name, :namevar => true) do
desc 'The name of the self IP object'

validate do |value|
raise(ArgumentError, "Must match pattern of /Partition/ObjectName") unless value =~ VALID_PARTITION
end
end

newproperty(:address) do
desc 'The IP address of the self IP object'

validate do |value|
raise(ArgumentError, 'Address must be a valid IP address.') unless IPAddr.new(value)
end
end

newproperty(:netmask) do
desc 'Netmask of the self IP object'

validate do |value|
raise(ArgumentError, 'Destination must be a valid IP address.') unless IPAddr.new(value)
end
end

newproperty(:vlan) do
desc 'VLAN or Tunnel name for the self IP object'

validate do |value|
raise(ArgumentError, "Must match pattern of /Partition/ObjectName") unless value =~ VALID_PARTITION
end
end

newproperty(:traffic_group) do
desc 'Traffic group for the self IP object'

validate do |value|
raise(ArgumentError, "Must match pattern of /Partition/ObjectName") unless value =~ VALID_PARTITION
end
end

newproperty(:floating_state) do
desc 'The floating state of the self IP object'

newvalue('STATE_ENABLED')
newvalue('STATE_DISABLED')
end
end
85 changes: 85 additions & 0 deletions lib/puppet/type/f5_vlan.rb
@@ -0,0 +1,85 @@
require 'ipaddr' # For validation.

Puppet::Type.newtype(:f5_vlan) do
@doc = 'Manage self IPs within the F5.'

apply_to_device
ensurable

VALID_PARTITION = /^\/.*\//

newparam(:name, :namevar => true) do
desc 'The name of the VLAN object'

validate do |value|
raise(ArgumentError, "Must match pattern of /Partition/ObjectName") unless value =~ VALID_PARTITION
end
end

newproperty(:vlan_id) do
desc 'The ID of the VLAN object'

newvalues(/^\d+$/)
end

newproperty(:members, :array_matching => :all) do
desc 'The list of interfaces/trunks that will be members of the VLAN.'
required_keys = ['member_name','member_type','tag_state']

validate do |value|
value = [ value ] unless value.is_a?(Array)

value.each do |hash|
unless required_keys.any? { |k| hash.key?(k) }
raise Puppet::Error, "Puppet::Type::F5_Vlan_Class: members property hash must include keys ${required_keys.join(', ')}."
end
unless hash['member_type'] =~ /^MEMBER_(INTERFACE|TRUNK)$/
raise Puppet::Error, "Puppet::Type::F5_Vlan_Class: members property hash key 'member_type' must have value 'MEMBER_INTERFACE' or 'MEMBER_TRUNK'."
end
unless hash['tag_state'] =~ /^MEMBER_(TAGGED|UNTAGGED)$/
raise Puppet::Error, "Puppet::Type::F5_Vlan_Class: members property hash key 'tag_state' must have value 'MEMBER_TAGGED' or 'MEMBER_UNTAGGED'."
end
end
end

def insync?(is)
is = [ is ] unless is.is_a?(Array)

is.sort!
should = @should.sort

# For some reason `is` hash keys are symbols and `@should` hash keys
# are strings. We want strings, so transform them.
is.each do |element|
element.keys.each do |key|
element[key.to_s] = element.delete(key)
end
end

return true if is == should
false
end

def should_to_s(newvalue)
newvalue
end

def is_to_s(currentvalue)
currentvalue
end
end

newproperty(:failsafe_state) do
desc 'Failsafe state value for the VLAN.'
defaultto 'STATE_DISABLED'

newvalues(/^STATE_(DISABLED|ENABLED)$/)
end

newproperty(:timeout) do
desc 'Failsafe timeout'
defaultto '90'

newvalues(/^\d+$/)
end
end
2 changes: 2 additions & 0 deletions lib/puppet/util/network_device/f5/device.rb
Expand Up @@ -28,6 +28,8 @@ def initialize(url, option = {})
'Management.SNMPConfiguration',
'Management.UserManagement',
'Networking.RouteTableV2',
'Networking.SelfIPV2',
'Networking.VLAN',
'System.ConfigSync',
'System.Inet',
'System.Session',
Expand Down

0 comments on commit 4cc4547

Please sign in to comment.