--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/ruby/puppet/files/solaris/lib/puppet/provider/evs/solaris.rb Tue Aug 18 15:07:30 2015 -0700
@@ -0,0 +1,236 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+Puppet::Type.type(:evs).provide(:evs) do
+ desc "Provider for managing EVS setup in the Solaris OS"
+ confine :operatingsystem => [:solaris]
+ defaultfor :osfamily => :solaris, :kernelrelease => ["5.11", "5.12"]
+ commands :evsadm => "/usr/sbin/evsadm"
+
+ mk_resource_methods
+
+ def initialize(value={})
+ super(value)
+ @property_flush = {}
+ end
+
+ def self.get_evs_list
+ begin
+ evs_list = evsadm("show-evs", "-c", "-o", "evs,tenant,status")
+ .split("\n")
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Unable to populate EVS instances: \n" \
+ "#{e.inspect}"
+ end
+ evs_list
+ end
+
+ def self.get_evs_properties(evs, tenant, status, ensure_val)
+ evs_properties = {}
+ evs_fullname = tenant + "/" + evs
+
+ evs_properties[:name] = evs_fullname
+ evs_properties[:status] = status
+ evs_properties[:ensure] = ensure_val
+
+ evsadm("show-evsprop", "-f", "tenant=#{tenant}", "-c", "-o",
+ "property,value", evs).split("\n").collect do |each_evsprop|
+ property, value = each_evsprop.split(":")
+ value = "" if value.nil?
+ case property
+ # read/write properties (always updatable)
+ when "maxbw"
+ evs_properties[:maxbw] = value
+ when "priority"
+ evs_properties[:priority] = value
+ when "protection"
+ evs_properties[:protection] = value
+ # read-only properties (settable upon cration)
+ when "l2-type"
+ evs_properties[:l2_type] = value
+ when "vlanid"
+ evs_properties[:vlanid] = value
+ when "vni"
+ evs_properties[:vni] = value
+ when "uuid"
+ evs_properties[:uuid] = value
+ end
+ end
+
+ Puppet.debug "EVS Properties: #{evs_properties.inspect}"
+ evs_properties
+ end
+
+ def self.instances
+ get_evs_list.collect do |each_evs|
+ evs, tenant, status = each_evs.strip.split(":")
+ evs_properties = get_evs_properties(evs, tenant, status, :present)
+ new(evs_properties) # Create a provider instance
+ end
+ end
+
+ def self.prefetch(resources)
+ instances.each do |inst|
+ if resource = resources[inst.name]
+ resource.provider = inst
+ end
+ end
+ end
+
+ def exists?
+ @property_hash[:ensure] == :present
+ end
+
+ def create
+ tenant, evs = get_tenant_and_evs_name
+ begin
+ create_evs(tenant, evs, add_properties(@resource))
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot create EVS: \n#{e.inspect}"
+ end
+ end
+
+ def destroy
+ tenant, evs = get_tenant_and_evs_name
+ begin
+ delete_evs(tenant, evs)
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot delete EVS: \n#{e.inspect}"
+ end
+ end
+
+ ### Define Setters ###
+ ## read/write properties (always updatable) ##
+ def maxbw=(value)
+ @property_flush[:maxbw] = value
+ end
+
+ def priority=(value)
+ @property_flush[:priority] = value
+ end
+
+ def protection=(value)
+ @property_flush[:protection] = value
+ end
+
+ ## read-only properties (settable upon creation) ##
+ def l2_type=(value)
+ raise Puppet::Error, "l2_type property is settable only upon creation"
+ end
+
+ def vlanid=(value)
+ raise Puppet::Error, "valid property is settable only upon creation"
+ end
+
+ def vni=(value)
+ raise Puppet::Error, "vni property is settable only upon creation"
+ end
+
+ def uuid=(value)
+ raise Puppet::Error, "uuid property is settable only upon creation"
+ end
+
+ # Create EVS instance
+ def create_evs(tenant, evs, properties)
+ begin
+ evsadm("create-evs", "-T", tenant, properties, evs)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ # Destroy EVS instance
+ def delete_evs(tenant, evs)
+ begin
+ evsadm("delete-evs", "-T", tenant, evs)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ # Set read/write property of EVS instance
+ def set_evsprop(tenant, evs, property)
+ begin
+ evsadm("set-evsprop", "-T", tenant, property, evs)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ # Parse the "name" value from user and yield tenant and EVS instance name
+ def get_tenant_and_evs_name()
+ usrstr = @resource[:name].split("/")
+ if usrstr.length == 2
+ return usrstr[0], usrstr[1]
+ else
+ raise Puppet::Error, "Invalid EVS name #{@resource[:name]} \n" \
+ "Name convention must be <tenant>/<evs>"
+ end
+ end
+
+ # property setter for EVS creation
+ def add_properties(source)
+ p = []
+ prop_list = {
+ "maxbw" => source[:maxbw],
+ "priority" => source[:priority],
+ "protection" => source[:protection],
+ "l2-type" => source[:l2_type],
+ "vlanid" => source[:vlanid],
+ "vni" => source[:vni],
+ "uuid" => source[:uuid]
+ }
+ prop_list.each do |key, value|
+ next if (value == nil) || (value == "")
+ p << "#{key}=#{value}"
+ end
+ return [] if p.empty?
+ properties = Array["-p", p.join(",")]
+ end
+
+ # Update property change
+ def flush
+ tenant, evs = get_tenant_and_evs_name
+
+ # Update property values when specified
+ unless @property_flush.empty?
+ # update multiple property values iteratively
+ @property_flush.each do |key, value|
+ prop = ["-p", "#{key}=#{value}"]
+ begin
+ set_evsprop(tenant, evs, prop)
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot update the property " \
+ "#{key}=#{value}.\n#{e.inspect}"
+ end
+ end
+ end
+ # Synchronize all the SHOULD values to IS values
+ @property_hash = resource.to_hash
+ end
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/ruby/puppet/files/solaris/lib/puppet/provider/evs_ipnet/solaris.rb Tue Aug 18 15:07:30 2015 -0700
@@ -0,0 +1,219 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+
+Puppet::Type.type(:evs_ipnet).provide(:evs_ipnet) do
+ desc "Provider for managing EVS IPnet setup in the Solaris OS"
+ confine :operatingsystem => [:solaris]
+ defaultfor :osfamily => :solaris, :kernelrelease => ["5.11", "5.12"]
+ commands :evsadm => "/usr/sbin/evsadm"
+
+ mk_resource_methods
+
+ def initialize(value={})
+ super(value)
+ @property_flush = {}
+ end
+
+ def self.get_ipnet_prop_list
+ begin
+ ipnet_list = evsadm("show-ipnet", "-c", "-o",
+ "name,tenant").split("\n")
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Unable to populate IPnet: \n"\
+ "#{e.inspect}"
+ end
+ ipnet_list
+ end
+
+ def self.get_ipnet_properties(ipnet_name, tenant, ensure_val)
+ ipnet_properties = {}
+ ipnet_fullname = tenant + "/" + ipnet_name
+
+ ipnet_properties[:name] = ipnet_fullname
+ ipnet_properties[:ensure] = ensure_val
+
+ evsadm("show-ipnetprop", "-f", "tenant=#{tenant}", "-c", "-o",
+ "property,value", ipnet_name).split("\n").collect do |each_ipnet|
+ property, value = each_ipnet.split(":")
+ value = "" if value.nil?
+ case property
+ # read-only properties (settable upon creation)
+ when "subnet"
+ ipnet_properties[:subnet] = value
+ when "defrouter"
+ ipnet_properties[:defrouter] = value
+ when "uuid"
+ ipnet_properties[:uuid] = value
+ # read/write property (always updatable)
+ when "pool"
+ ipnet_properties[:pool] = value
+ end
+ end
+
+ Puppet.debug "IPnet Properties: #{ipnet_properties.inspect}"
+ ipnet_properties
+ end
+
+ def self.instances
+ get_ipnet_prop_list.collect do |each_ipnet|
+ ipnet, tenant, subnet = each_ipnet.strip.split(":")
+ ipnet_properties = get_ipnet_properties(
+ ipnet, tenant, :present)
+ new(ipnet_properties) # Create a provider instance
+ end
+ end
+
+ def self.prefetch(resources)
+ instances.each do |inst|
+ if resource = resources[inst.name]
+ resource.provider = inst
+ end
+ end
+ end
+
+ def exists?
+ @property_hash[:ensure] == :present
+ end
+
+ def create
+ # Subnet value is required to create an IPnet instance
+ if @resource[:subnet].nil?
+ raise Puppet::Error, "Subnet value is missing"
+ end
+
+ tenant, ipnet_name = get_tenant_and_ipnet_name
+ begin
+ create_ipnet(tenant, ipnet_name, add_properties(@resource))
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot add the IPnet: \n #{e.inspect}"
+ end
+ end
+
+ def destroy
+ tenant, ipnet_name = get_tenant_and_ipnet_name
+ begin
+ delete_ipnet(tenant, ipnet_name)
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot remove the IPnet: \n #{e.inspect}"
+ end
+ end
+
+ ## read-only properties (settable upon creation) ##
+ def defrouter=(value)
+ raise Puppet::Error, "defrouter property is settable only upon creation"
+ end
+
+ def subnet=(value)
+ raise Puppet::Error, "subnet property is settable only upon creation"
+ end
+
+ def uuid=(value)
+ raise Puppet::Error, "uuid property is settable only upon creation"
+ end
+
+ ## read/write property (always updatable) ##
+ def pool=(value)
+ @property_flush[:pool] = value
+ end
+
+ ## Create IPnet instance ##
+ def create_ipnet(tenant, ipnet_name, properties)
+ begin
+ evsadm("add-ipnet", "-T", tenant, properties, ipnet_name)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ ## Remove IPnet instance ##
+ def delete_ipnet(tenant, ipnet_name)
+ begin
+ evsadm("remove-ipnet", "-T", tenant, ipnet_name)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ ## Set IPnet prop (pool property only) ##
+ def set_ipnet(tenant, ipnet_name, property)
+ begin
+ evsadm("set-ipnetprop", "-T", tenant, property, ipnet_name)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ ## Parse the "name" value from user and yield tenant and IPnet name ##
+ def get_tenant_and_ipnet_name
+ fullname = @resource[:name]
+
+ parsed_val = fullname.strip.split("/")
+ if (parsed_val.length != 3)
+ raise Puppet::Error, "Invalid IPnet name"
+ end
+ tenant, evs, ipnet = parsed_val
+ return tenant, evs + "/" + ipnet
+ end
+
+ ## property setter for IPnet creation ##
+ def add_properties(source)
+ p = []
+ prop_list = {
+ "defrouter" => source[:defrouter],
+ "pool" => source[:pool],
+ "subnet" => source[:subnet],
+ "uuid" => source[:uuid]
+ }
+ prop_list.each do |key, value|
+ next if (value == nil) || (value == "")
+ p << "#{key}=#{value}"
+ end
+ return [] if p.empty?
+ properties = Array["-p", p.join(",")]
+ end
+
+ ## Flush when existing property value is updatable ##
+ def flush
+ tenant, ipnet_name = get_tenant_and_ipnet_name
+
+ unless @property_flush.empty?
+ # Update read/write property (pool)
+ pool_prop = ["-p", "pool=#{@property_flush[:pool]}"]
+ begin
+ set_ipnet(tenant, ipnet_name, pool_prop)
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot update the pool property. \n" \
+ "#{e.inspect}"
+ end
+ end
+
+ # Synchronize all the SHOULD values to IS values
+ @property_hash = resource.to_hash
+ end
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/ruby/puppet/files/solaris/lib/puppet/provider/evs_properties/solaris.rb Tue Aug 18 15:07:30 2015 -0700
@@ -0,0 +1,294 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+
+Puppet::Type.type(:evs_properties).provide(:evs_properties) do
+ desc "Provider for managing Oracle Solaris EVS properties"
+ confine :operatingsystem => [:solaris]
+ defaultfor :osfamily => :solaris, :kernelrelease => ["5.11", "5.12"]
+ commands :evsadm => "/usr/sbin/evsadm"
+
+ mk_resource_methods
+
+ def initialize(value={})
+ super(value)
+ @property_flush = {}
+ end
+
+ def self.get_client_property
+ client_property = {}
+ begin
+ p = evsadm("show-prop", "-c", "-o", "property,value")
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Failed to prefetch client property: \n" \
+ "#{e.inspect}"
+ end
+
+ property, value = p.strip.split(":", 2)
+ value.gsub! "\\:", ":"
+ client_property[:name] = "client_property"
+ client_property[:controller] = value
+
+ Puppet.debug "Client Property: #{client_property.inspect}"
+ client_property
+
+ end
+
+ def self.get_control_properties
+ control_props = {}
+ uplink_ports = []
+ uri_templates = []
+ vxlan_addrs = []
+ begin
+ evsadm("show-controlprop", "-c", "-o",
+ "property,value,vlan_range,vxlan_range,host,flat").\
+ split("\n").collect do |each_prop|
+ each_prop.gsub! "\\:", "\\"
+ property, value, vlan_range, vxlan_range, host, flat = \
+ each_prop.strip().split(":")
+ case property
+ when "l2-type"
+ control_props[:l2_type] = value
+ when "uplink-port"
+ next if value.empty?
+ host = "" if host == nil
+ val = "#{value};#{vlan_range};#{vxlan_range};#{host};"\
+ "#{flat}"
+ uplink_ports << val
+ when "uri-template"
+ value.gsub! "\\", ":"
+ host = "" if host == nil
+ val = "#{value};#{host}"
+ uri_templates << val
+ when "vlan-range"
+ control_props[:vlan_range] = value
+ when "vxlan-addr"
+ host = "" if host == nil
+ val = "#{value};#{vxlan_range};#{host}"
+ vxlan_addrs << val
+ when "vxlan-ipvers"
+ control_props[:vxlan_ipvers] = value
+ when "vxlan-mgroup"
+ control_props[:vxlan_mgroup] = value
+ when "vxlan-range"
+ control_props[:vxlan_range] = value
+ end
+ end
+ rescue Puppet::ExecutionFailure => e
+ # EVS controller is not set or valid
+ # Handle the exception at upper level
+ raise
+ end
+ control_props[:name] = "controller_property"
+ control_props[:uplink_port] = uplink_ports
+ control_props[:uri_template] = uri_templates
+ control_props[:vxlan_addr] = vxlan_addrs
+ Puppet.debug "Control Properties: #{control_props.inspect}"
+ control_props
+ end
+
+ def self.instances
+ prop_instance = []
+ client_property = get_client_property
+ prop_instance << new(client_property)
+
+ begin
+ controller_property = get_control_properties
+ rescue Puppet::ExecutionFailure => e
+ # EVS controller is not set or invalid
+ prop_instance << new({:name => "controller_property"})
+ else
+ # controller_property values are fetched
+ prop_instance << new(controller_property)
+ end
+ prop_instance
+ end
+
+ def self.prefetch(resources)
+ instances.each do |inst|
+ if resource = resources[inst.name]
+ resource.provider = inst
+ end
+ end
+ end
+
+ ### Define Setters ###
+ ## Controller side property setup ##
+
+ def l2_type=(value)
+ @property_flush[:l2_type] = value
+ end
+
+ def uplink_port=(value)
+ @property_flush[:uplink_port] = value
+ end
+
+ def uri_template=(value)
+ @property_flush[:uri_template] = value
+ end
+
+ def vlan_range=(value)
+ @property_flush[:vlan_range] = value
+ end
+
+ def vxlan_addr=(value)
+ @property_flush[:vxlan_addr] = value
+ end
+
+ def vxlan_ipvers=(value)
+ @property_flush[:vxlan_ipvers] = value
+ end
+
+ def vxlan_mgroup=(value)
+ @property_flush[:vxlan_mgroup] = value
+ end
+
+ def vxlan_range=(value)
+ @property_flush[:vxlan_range] = value
+ end
+
+ ## Client side property setup: the pointer to the EVS controller ##
+ def controller=(value)
+ @property_flush[:controller] = value
+ end
+
+ def set_controller_property(host, property)
+ begin
+ evsadm("set-controlprop", host, property)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ def set_client_property(property)
+ begin
+ evsadm("set-prop", "-p", property)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ def flush
+ case @resource[:name]
+ when "controller_property"
+ if @property_flush.has_key?(:controller)
+ puts "foo"
+ raise Puppet::Error, "controller_property does not have "\
+ "'controller' property. Try client_property"
+ puts "bar"
+ end
+
+ props = []
+ @property_flush.each do |key, value|
+ # Change symbol to string
+ k = key.to_s.gsub! "_", "-"
+ case k
+ # uplink-port property takes up to five values:
+ # link, [vlan-range], [vxlan-range], [host] and [flat]
+ when "uplink-port"
+ link, vlan, vxlan, host, flat = \
+ value.strip().split(";", -1)
+
+ # store host parameter if exists
+ host = host != "" ? ["-h", host] : []
+
+ # Concatenate the parameters of uplink-port
+ link = "uplink-port=#{link}"
+ vlan = vlan != "" ? ",vlan-range=#{vlan}" : ""
+ vxlan = vxlan != "" ? ",vxlan-range=#{vxlan}" : ""
+ flat = flat != "" ? ",flat=#{flat}" : ""
+
+ p = ["-p", "#{link}#{vlan}#{vxlan}#{flat}"]
+
+ props << [host, p]
+
+ # uri-template property takes up to two values:
+ # uri and [host]
+ when "uri-template"
+ uri, host = value.strip().split(";", -1)
+
+ # store host parameter if exists
+ host = host != "" ? ["-h", host] : []
+ uri = ["-p", "uri-template=#{uri}"]
+
+ props << [host, uri]
+
+ # vxlan_addr property takes up to three values:
+ # vxlan-addr, [vxlan-range] and [host]
+ when "vxlan-addr"
+ addr, range, host = value.strip().split(";", -1)
+
+ # store host parameter if exists
+ host = host != "" ? ["-h", host] : []
+ addr = "vxlan-addr=#{addr}"
+ range = range != "" ? ",vxlan-range=#{range}" : ""
+
+ p = ["-p", "#{addr}#{range}"]
+
+ props << [host, p]
+
+ # l2-type, vlan-range, vxlan-range, vxlan-ipvers
+ # and vxlan-mgroup properties just need values
+ else
+ host = []
+ p = ["-p", "#{k}=#{value}"]
+ props << [host, p]
+ end
+ end
+
+ # Reverse the array so that l2-type, vlan-range, vxlan-range
+ # vxlan-ipvers and vxlan-mgroups are set before the others
+ props.reverse!
+ # iteratively set controller property
+ props.each do |p|
+ begin
+ set_controller_property(p[0], p[1])
+ # Do not terminate the script even if there is an error
+ # Just continue to next script
+ rescue Puppet::ExecutionFailure => e
+ Puppet.err "Cannot apply the property: \n#{e.inspect}"
+ end
+ end
+
+ when "client_property"
+ unless @property_flush.has_key?(:controller)
+ raise Puppet::Error,
+ "'controller' property must be specified"
+ end
+ prop = "controller=#{@property_flush[:controller]}"
+ begin
+ set_client_property(prop)
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot apply the property:\n #{e.inspect}"
+ end
+ end
+
+ # Synchronize all the SHOULD values to IS values
+ @property_hash = resource.to_hash
+ end
+end
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/ruby/puppet/files/solaris/lib/puppet/provider/evs_vport/solaris.rb Tue Aug 18 15:07:30 2015 -0700
@@ -0,0 +1,257 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+
+Puppet::Type.type(:evs_vport).provide(:evs_vport) do
+ desc "Provider for managing EVS VPort setup in the Solaris OS"
+ confine :operatingsystem => [:solaris]
+ defaultfor :osfamily => :solaris, :kernelrelease => ["5.11", "5.12"]
+ commands :evsadm => "/usr/sbin/evsadm"
+
+ mk_resource_methods
+
+ def initialize(value={})
+ super(value)
+ @property_flush = {}
+ end
+
+ def self.get_vport_list
+ begin
+ vport_list = evsadm("show-vport", "-c", "-o",
+ "name,tenant,status").split("\n")
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "unable to populate VPort instances: \n" \
+ "#{e.inspect}"
+ return nil
+ end
+ vport_list
+ end
+
+ def self.get_vport_properties(vport, tenant, status, ensure_val)
+ vport_props = {}
+ vport_fullname = tenant + "/" + vport
+ vport_props[:name] = vport_fullname
+ vport_props[:status] = status
+ vport_props[:ensure] = ensure_val
+
+ evsadm("show-vportprop", "-f", "tenant=#{tenant}", "-c", "-o",
+ "property,value", vport).split("\n").collect do |each_prop|
+ property, value = each_prop.split(":", 2)
+ value = "" if value.nil?
+ case property
+ # read/write properties (always updatable)
+ when "cos"
+ vport_props[:cos] = value
+ when "maxbw"
+ vport_props[:maxbw] = value
+ when "priority"
+ vport_props[:priority] = value
+ when "protection"
+ vport_props[:protection] = value
+ # read-only properties (settable upon creation)
+ when "ipaddr"
+ vport_props[:ipaddr] = value
+ when "macaddr"
+ # macaddr ":" appears to be "\:". change it to ":"
+ vport_props[:macaddr] = value.gsub! "\\:", ":"
+ when "uuid"
+ vport_props[:uuid] = value
+ end
+ end
+
+ Puppet.debug "VPort properties: #{vport_props.inspect}"
+ vport_props
+ end
+
+ def self.instances
+ get_vport_list.collect do |each_vport|
+ vport, tenant, status = each_vport.strip.split(":")
+ vport_props = get_vport_properties(vport, tenant, status, :present)
+ new(vport_props) # Create a provider instance
+ end
+ end
+
+ def self.prefetch(resources)
+ instances.each do |inst|
+ if resource = resources[inst.name]
+ resource.provider = inst
+ end
+ end
+ end
+
+ def exists?
+ @property_hash[:ensure] == :present
+ end
+
+ def create
+ tenant, vport = get_tenant_and_vport_name
+ begin
+ create_vport(tenant, vport, add_properties(@resource))
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot add VPort: \n #{e.inspect}"
+ end
+ end
+
+ def destroy
+ tenant, vport = get_tenant_and_vport_name
+ begin
+ delete_vport(tenant, vport)
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot remove VPort: \n #{e.inspect}"
+ end
+ end
+
+ def reset
+ tenant, vport = get_tenant_and_vport_name
+ begin
+ evsadm("reset-vport", "-T", tenant, vport)
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot reset VPort: \n #{e.inspect}"
+ end
+
+ @resource[:ensure] = :present
+ Puppet::notice "The VPort has been successfully reset."
+ end
+
+ ### Define Setters ###
+ ## read/write properties (always updatable) ##
+ def cos=(value)
+ @property_flush[:cos] = value
+ end
+
+ def maxbw=(value)
+ @property_flush[:maxbw] = value
+ end
+
+ def priority=(value)
+ @property_flush[:priority] = value
+ end
+
+ def protection=(value)
+ @property_flush[:protection] = value
+ end
+
+ ## read-only properties (settable upon creation) ##
+ def ipaddr=(value)
+ raise Puppet::Error, "ipaddr property is settable only upon creation"
+ end
+
+ def macaddr=(value)
+ raise Puppet::Error, "macaddr property is settable only upon creation"
+ end
+
+ def uuid=(value)
+ raise Puppet::Error, "uuid property is settable only upon creation"
+ end
+
+ # Add VPort Instance
+ def create_vport(tenant, vport, properties)
+ begin
+ evsadm("add-vport", "-T", tenant, properties, vport)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ # Remove Vport Instance
+ def delete_vport(tenant, vport)
+ begin
+ evsadm("remove-vport", "-T", tenant, vport)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ # set read/write property
+ def set_vportprop(tenant, vport, property)
+ begin
+ evsadm("set-vportprop", "-T", tenant, property, vport)
+ rescue Puppet::ExecutionFailure => e
+ # Pass up the exception to upper level
+ raise
+ end
+ end
+
+ # Parse the "name" value from user and yield tenant and vport name
+ def get_tenant_and_vport_name
+ fullname = @resource[:name]
+
+ return [] if fullname == nil
+ parsed_val = fullname.strip.split("/")
+ if (parsed_val.length != 3)
+ raise Puppet::Error, "Invalid VPort name #{@resource[:name]} \n" \
+ "Name convention must be <tenant>/<evs>/<vport>"
+ end
+ tenant, evs, vport = parsed_val
+ return tenant, evs + "/" + vport
+ end
+
+ # property setter for vport creation
+ def add_properties(source)
+ p = []
+ if source[:ipaddr] != nil
+ source[:ipaddr] = source[:ipaddr].split('/')[0]
+ end
+ prop_list = {
+ "cos" => source[:cos],
+ "maxbw" => source[:maxbw],
+ "priority" => source[:priority],
+ "protection" => source[:protection],
+ "ipaddr" => source[:ipaddr],
+ "macaddr" => source[:macaddr],
+ "uuid" => source[:uuid]
+ }
+ prop_list.each do |key, value|
+ next if (value == "") || (value == nil)
+ p << "#{key}=#{value}"
+ end
+ return [] if p.empty?
+ properties = Array["-p", p.join(",")]
+ end
+
+ # Update property change
+ def flush
+ tenant, vport = get_tenant_and_vport_name
+
+ # Update property values when specified
+ unless @property_flush.empty?
+ # update multiple property values iteratively
+ @property_flush.each do |key, value|
+ prop = ["-p", "#{key}=#{value}"]
+ begin
+ set_vportprop(tenant, vport, prop)
+ rescue Puppet::ExecutionFailure => e
+ raise Puppet::Error, "Cannot update the property " \
+ "#{key}=#{value}.\n#{e.inspect}"
+ end
+ end
+ end
+
+ # Synchronize all the SHOULD values to IS values
+ @property_hash = resource.to_hash
+ end
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/ruby/puppet/files/solaris/lib/puppet/type/evs.rb Tue Aug 18 15:07:30 2015 -0700
@@ -0,0 +1,83 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+Puppet::Type.newtype(:evs) do
+ @doc = "Manage the configuration of Oracle Solaris Elastic Virtual Switch
+ (EVS)"
+
+ ensurable
+ newparam(:name) do
+ desc "The full name for EVS (including the tenant name)"
+ validate do |value|
+ if value.split("/").length != 2
+ raise Puppet::Error, "Invalid EVS name\n"\
+ "Name convention must be <tenant>/<evs>"
+ end
+ end
+ end
+
+ ## read/write properties (always updatable) ##
+ newproperty(:maxbw) do
+ desc "The full duplex bandwidth for the virtual port"
+ end
+
+ newproperty(:priority) do
+ desc "The relative priority for the virtual port"
+ newvalues("high", "medium", "low", "")
+ end
+
+ newproperty(:protection) do
+ desc "Enables one or more types of link protection"
+ # verify protection value: comma(,) separatable
+ validate do |value|
+ value.split(",").collect do |each_val|
+ if not ["mac-nospoof", "restricted", "ip-nospoof",
+ "dhcp-nospoof", "none", ""].include? each_val
+ raise Puppet::Error, "Invalid value \"#{each_val}\". "\
+ "Valid values are mac-nospoof, restricted, "\
+ "ip-nospoof, dhcp-nospoof, none."
+ end
+ end
+ end
+ end
+
+ ## read-only properties (settable upon creation) ##
+ newproperty(:l2_type) do
+ desc "Define how an EVS will be implemented across machines"
+ newvalues("vlan", "vxlan", "flat", "")
+ end
+
+ newproperty(:vlanid) do
+ desc "VXLAN segment ID used to implement the EVS"
+ end
+
+ newproperty(:vni) do
+ desc "VLAN ID used to implement the EVS"
+ end
+
+ newproperty(:uuid) do
+ desc "UUID of the EVS instance"
+ end
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/ruby/puppet/files/solaris/lib/puppet/type/evs_ipnet.rb Tue Aug 18 15:07:30 2015 -0700
@@ -0,0 +1,58 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+Puppet::Type.newtype(:evs_ipnet) do
+ @doc = "Manage the configuration of IPnet (subnet of IPv4 or IPv6
+ addresses)"
+
+ ensurable
+ newparam(:name) do
+ desc "The full name of IPnet including tenant name"
+ validate do |value|
+ if value.split("/").length != 3
+ raise Puppet::Error, "Invalid IPnet name\n"\
+ "Name convention must be <tenant>/<evs>/<ipnet>"
+ end
+ end
+ end
+
+ ## read-only properties (updatable when idle) ##
+ newproperty(:subnet) do
+ desc "Subnet (either IPv4 or IPv6) for the IPnet"
+ end
+
+ newproperty(:defrouter) do
+ desc "The IP address of the default router for the given IPnet"
+ end
+
+ newproperty(:uuid) do
+ desc "UUID of the IPnet"
+ end
+
+ ## read/write property (settable upon creation) ##
+ newproperty(:pool) do
+ desc "Sub-ranges of IP addresses within a subnet"
+ end
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/ruby/puppet/files/solaris/lib/puppet/type/evs_properties.rb Tue Aug 18 15:07:30 2015 -0700
@@ -0,0 +1,154 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+Puppet::Type.newtype(:evs_properties) do
+ @doc = "Manage global properties of EVS(Elastic Virtual Switch) for both
+ client and controller. There are two instances associated with
+ contoller and client properties respectively"
+
+ ## This is a property setter, thus not ensurable ##
+ newparam(:name) do
+ desc "Type of properties\n"\
+ "Names are preset to 'controller_property' and 'client_property'"
+ # Validate the name:
+ # Names are preset to "controller_property" and "client_property"
+ validate do |value|
+ if value != "controller_property" && value != "client_property"
+ raise Puppet::Error, "Invalid property type name\n" \
+ "Name must be either 'controller_property' or " \
+ "'client_property'"
+ end
+ end
+ end
+
+ ## Properties associated with "controller_property" ##
+ ## All the properties are read/write
+ newproperty(:l2_type) do
+ desc "Define how an EVS will be implemented across machines "\
+ "(controller_property)"
+ newvalues("vlan", "vxlan", "flat", "")
+ end
+
+ newproperty(:uplink_port) do
+ desc "Specifies the datalink to be used for VLANs or VXLANs "\
+ "(controller_property)\n"\
+ "uplink_port value must be in the format of either\n"\
+ "uplink_port=<uplink> or \n"\
+ "uplink_port='<uplink>;[<vlan-range>];[<vxlan-range>];"\
+ "[<host>];[<flat>]'"
+ # Use munge to support single value input
+ munge do |value|
+ uplink_list = value.strip().split(";", -1)
+ if uplink_list.length == 0
+ value = ";;;;"
+ elsif uplink_list.length == 1
+ value = "#{value};;;;"
+ elsif uplink_list.length == 5
+ value
+ else
+ raise Puppet::Error, "Invalid uplink_port format: \n" \
+ "The format must be uplink_port=<uplink> or " \
+ "uplink_port='<uplink>;[<vlan-range>];[<vxlan-range>];" \
+ "[<host>];[<flat>]'"
+ end
+ end
+ end
+
+ newproperty(:uri_template) do
+ desc "URI for per-EVS Node RAD Connection (controller_property)\n"\
+ "The syntax of the uri_template value will be of the form:\n"\
+ "uri_template='ssh://[username@][;<host>]' or \n"\
+ "uri_template='unix://[username@][;<host>]'"
+ # Use munge to support single value input
+ munge do |value|
+ uri_list = value.strip().split(";", -1)
+ if uri_list.length == 0
+ value = ";"
+ elsif uri_list.length == 1
+ value = "#{value};"
+ elsif uri_list.length == 2
+ value
+ else
+ raise Puppet::Error, "Invalid uri_template format: \n"\
+ "The format of the uri_template value must be\n"\
+ "uri_template='ssh://[username@][;<host>]' or \n"\
+ "uri_template='unix://[username@][;<host>]'"
+ end
+ end
+ end
+
+
+ newproperty(:vlan_range) do
+ desc "List of VLAN ID ranges that will be used for creating EVS "\
+ "(controller_property)\n"\
+ "The maximum valid range is 1-4094"
+ end
+
+ newproperty(:vxlan_addr) do
+ desc "IP address on top of which VXLAN datalink should be created "\
+ "(controller_property)\n"\
+ "The syntax of the vxlan_addr value will be of the form:\n"\
+ "vxlan_addr=<vxlan_IP_addr> or"\
+ "vxlan_addr='<vxlan_IP_addr>;[<vxlan-range>];[<host>]'"
+ # Use munge to support single value input
+ munge do |value|
+ vxlan_list = value.strip().split(";", -1)
+ if vxlan_list.length == 0
+ value = ";;"
+ elsif vxlan_list.length == 1
+ value = "#{value};;"
+ elsif vxlan_list.length == 3
+ value
+ else
+ raise Puppet::Error, "Invalid vxlan_addr format: \n" \
+ "The format of the vxlan_addr value must be\n"\
+ "vxlan_addr=<vxlan_IP_addr> or"\
+ "vxlan_addr='<vxlan_IP_addr>;[<vxlan-range>];[<host>]'"
+ end
+ end
+ end
+
+ newproperty(:vxlan_ipvers) do
+ desc "IP version of the address for VXLAN datalinks "\
+ "(controller_property)"
+ end
+
+ newproperty(:vxlan_mgroup) do
+ desc "Multicast address that needs to be used while creating VXLAN" \
+ " links (controller_property)"
+ end
+
+ newproperty(:vxlan_range) do
+ desc "List of VXLAN ID ranges that will be used for creating EVS "\
+ "(controller_property)\n"\
+ "The maximum valid range is 0-16777215"
+ end
+
+
+ ### The read/write property associated with "client_property" ###
+ newproperty(:controller) do
+ desc "SSH address of EVS controller server (client_property)"
+ end
+end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/ruby/puppet/files/solaris/lib/puppet/type/evs_vport.rb Tue Aug 18 15:07:30 2015 -0700
@@ -0,0 +1,97 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+#
+
+Puppet::Type.newtype(:evs_vport) do
+ @doc = "Manage the configuration of EVS VPort"
+
+ ensurable do
+ newvalue(:present) do
+ provider.create
+ end
+
+ newvalue(:absent) do
+ provider.destroy
+ end
+
+ # Resets the specified VPort
+ newvalue(:reset) do
+ provider.reset
+ end
+ end
+
+ newparam(:name) do
+ desc "The full name of Virtual Port for EVS"
+ munge do |value|
+ if value.split("/").length != 3
+ raise Puppet::Error, "Invalid VPort name\n" \
+ "Name convention must be <tenant>/<evs>/<vport>"
+ else
+ value
+ end
+ end
+ end
+
+ ## read/write properties (always updatable) ##
+ newproperty(:cos) do
+ desc "802.1p priority on outbound packets on the virtual port"
+ end
+
+ newproperty(:maxbw) do
+ desc "The full duplex bandwith for the virtual port"
+ end
+
+ newproperty(:priority) do
+ desc "Relative priority of virtual port"
+ newvalues("high", "medium", "low", "")
+ end
+
+ newproperty(:protection) do
+ desc "Enables one or more types of link protection"
+ # verify protection value: comma(,) separatable
+ validate do |value|
+ value.split(",").collect do |each_val|
+ if not ["mac-nospoof", "restricted", "ip-nospoof",
+ "dhcp-nospoof", "none", ""].include? each_val
+ raise Puppet::Error, "Invalid value \"#{each_val}\". "\
+ "Valid values are mac-nospoof, restricted, "\
+ "ip-nospoof, dhcp-nospoof, none."
+ end
+ end
+ end
+ end
+
+ ## read-only properties (Settable upon creation) ##
+ newproperty(:ipaddr) do
+ desc "The IP address associated with the virtual port"
+ end
+
+ newproperty(:macaddr) do
+ desc "The MAC address associated with the virtual port"
+ end
+
+ newproperty(:uuid) do
+ desc "UUID of the virtual port"
+ end
+end
--- a/components/ruby/puppet/puppet-GENFRAG.p5m Tue Aug 18 13:55:16 2015 -0700
+++ b/components/ruby/puppet/puppet-GENFRAG.p5m Tue Aug 18 15:07:30 2015 -0700
@@ -42,6 +42,18 @@
file files/solaris/lib/puppet/provider/etherstub/solaris.rb \
path=etc/puppet/modules/solaris/lib/puppet/provider/etherstub/solaris.rb \
mode=0555
+file files/solaris/lib/puppet/provider/evs/solaris.rb \
+ path=etc/puppet/modules/solaris/lib/puppet/provider/evs/solaris.rb \
+ mode=0555
+file files/solaris/lib/puppet/provider/evs_ipnet/solaris.rb \
+ path=etc/puppet/modules/solaris/lib/puppet/provider/evs_ipnet/solaris.rb \
+ mode=0555
+file files/solaris/lib/puppet/provider/evs_properties/solaris.rb \
+ path=etc/puppet/modules/solaris/lib/puppet/provider/evs_properties/solaris.rb \
+ mode=0555
+file files/solaris/lib/puppet/provider/evs_vport/solaris.rb \
+ path=etc/puppet/modules/solaris/lib/puppet/provider/evs_vport/solaris.rb \
+ mode=0555
file files/solaris/lib/puppet/provider/interface_properties/solaris.rb \
path=etc/puppet/modules/solaris/lib/puppet/provider/interface_properties/solaris.rb \
mode=0555
@@ -108,6 +120,14 @@
path=etc/puppet/modules/solaris/lib/puppet/type/dns.rb mode=0555
file files/solaris/lib/puppet/type/etherstub.rb \
path=etc/puppet/modules/solaris/lib/puppet/type/etherstub.rb mode=0555
+file files/solaris/lib/puppet/type/evs.rb \
+ path=etc/puppet/modules/solaris/lib/puppet/type/evs.rb mode=0555
+file files/solaris/lib/puppet/type/evs_ipnet.rb \
+ path=etc/puppet/modules/solaris/lib/puppet/type/evs_ipnet.rb mode=0555
+file files/solaris/lib/puppet/type/evs_properties.rb \
+ path=etc/puppet/modules/solaris/lib/puppet/type/evs_properties.rb mode=0555
+file files/solaris/lib/puppet/type/evs_vport.rb \
+ path=etc/puppet/modules/solaris/lib/puppet/type/evs_vport.rb mode=0555
file files/solaris/lib/puppet/type/interface_properties.rb \
path=etc/puppet/modules/solaris/lib/puppet/type/interface_properties.rb \
mode=0555
@@ -197,5 +217,5 @@
home-dir=/etc/puppet login-shell=/bin/false uid=40
license puppet.license license="Apache v2.0"
-# Only ruby 1.9 puppet packages are currently available
-depend type=require-any fmri=pkg:/runtime/ruby-19
+# Any version of Ruby currently available
+depend type=require-any fmri=runtime/ruby-19 fmri=runtime/ruby-21