components/ruby/puppet-modules/oracle-solaris_providers/files/etc/puppet/modules/solaris_providers/lib/puppet/provider/evs/solaris.rb
author Shawn Ferry <shawn.ferry@oracle.com>
Wed, 10 Feb 2016 22:10:43 -0500
changeset 5438 c068f8c677e8
parent 4801 components/ruby/puppet/files/solaris/lib/puppet/provider/evs/solaris.rb@c249904bb056
permissions -rw-r--r--
PSARC/2016/016 Rename/Refactor Puppet and Puppet Module Packages 21041932 puppet, facter, and hiera need to build Ruby 2.1 packages 21042030 puppet, facter, and hiera need to stop building Ruby 1.9 packages 21613616 oracle-solaris_provider builds should come from the github repo we publish 22047789 puppet package name and dependencies are confusing 22301978 Overzealous use of $(RUBY_VERSION) in puppet packaging 22347610 GIT repos cannot be used as described in docs 22664785 Puppet module files should be owned by puppet 22675056 git clone could use --depth 1

#
# 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 creation)
            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