components/ruby/puppet/files/solaris/lib/puppet/provider/evs_properties/solaris.rb
changeset 4794 be62c55aa235
child 4801 c249904bb056
--- /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
+