PSARC/2015/218 Add EVS support to Puppet
authorSungmin Lee <sungmin.lee@oracle.com>
Tue, 18 Aug 2015 15:07:30 -0700
changeset 4794 be62c55aa235
parent 4793 24053a14d972
child 4795 17cca748f778
PSARC/2015/218 Add EVS support to Puppet 18043918 Add EVS support to Puppet
components/ruby/puppet/files/solaris/lib/puppet/provider/evs/solaris.rb
components/ruby/puppet/files/solaris/lib/puppet/provider/evs_ipnet/solaris.rb
components/ruby/puppet/files/solaris/lib/puppet/provider/evs_properties/solaris.rb
components/ruby/puppet/files/solaris/lib/puppet/provider/evs_vport/solaris.rb
components/ruby/puppet/files/solaris/lib/puppet/type/evs.rb
components/ruby/puppet/files/solaris/lib/puppet/type/evs_ipnet.rb
components/ruby/puppet/files/solaris/lib/puppet/type/evs_properties.rb
components/ruby/puppet/files/solaris/lib/puppet/type/evs_vport.rb
components/ruby/puppet/puppet-GENFRAG.p5m
--- /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