Hi list,

i wrote a simple type and provider to manage logical volumes with
puppet. This is my first attempt and it may not match the puppet
styles and best practices. I'm hoping for your improvement
suggestions.

Type:
=====

Puppet::Type.newtype(:logicalvolume) do
    @doc = "Manage logical volumes"

    ensurable

    newparam(:lvname) do
        desc "The logcal volumes name"

        validate do |value|
            unless value =~ /^[a-z0-9]+/
                raise ArgumentError , "%s is not a valid lv name" %
value
            end
        end

        isnamevar
    end

    newproperty(:size) do
        desc "The size in M or G"

        validate do |value|
            unless value =~ /^[0-9]+[MGTPE]/
                raise ArgumentError , "%s is not a valid lv size" %
value
            end
        end
    end

    newparam(:vg) do
        desc "The volumevg to create the volume in"

        validate do |value|
            unless value =~ /^[a-z0-9]+/
                raise ArgumentError , "%s is not a valid lv name" %
value
            end
        end
    end
end

Provider:
========

Puppet::Type.type(:logicalvolume).provide(:logicalvolume) do

    include Puppet::Util

    def size
        lvm_size_units = { "M" => 1024, "G" => 1048576, "T" =>
1073741824, "P" => 1099511627776, "E" => 1125899906842624 }
        lvm_size_units_match = lvm_size_units.keys().join('|')

        output = Puppet::Util.execute(["lvs", "--noheading", "/dev/
#{resource[:vg]}/#{resource[:name]}", "-o", "size"])

        if output =~ /^\s+(\d+)\.\d+
(#{lvm_size_units_match.downcase})/
            size = $1 + $2.capitalize
            debug("Size of /dev/#{resource[:vg]}/#{resource[:name]} is
#{size}")
            return size
        else
            fail("Failed to parse current volume size!")
        end
    end

    def size=(size)

        lvm_size_units = { "M" => 1024, "G" => 1048576, "T" =>
1073741824, "P" => 1099511627776, "E" => 1125899906842624 }
        lvm_size_units_match = lvm_size_units.keys().join('|')

        resizeable = false
        c_size = self.size()

        if size =~ /(\d+)(#{lvm_size_units_match})/
            n_size_bytes = $1.to_i
            n_size_unit  = $2
        end

        if c_size =~ /(\d+)(#{lvm_size_units_match})/
            c_size_bytes = $1.to_i
            c_size_unit  = $2
        end

        ## Check if given requested size matches extend size of VG
        output = Puppet::Util.execute(["vgdisplay", "-c",
resource[:vg]])
        vg_extend = output.split(':')[12].to_i

        if n_size_bytes * lvm_size_units[n_size_unit] % vg_extend != 0
            fail("Cannot extend to size #{size} because VG extend is
#{vg_extend}KB")
        end

        ## Veritfy that it's a extend: Only extends are allowed
        if lvm_size_units[c_size_unit] < lvm_size_units[n_size_unit]
            resizeable = true
        elsif lvm_size_units[c_size_unit] ==
lvm_size_units[n_size_unit]
            if n_size_bytes > c_size_bytes
                resizeable = true
            end
        end

        if not resizeable
            fail("Cannot change size of /dev/#{resource[:vg]}/
#{resource[:name]} as #{size} < #{c_size}")
        else
            output = Puppet::Util.execute(["lvextend", "-L", size, "/
dev/#{resource[:vg]}/#{resource[:name]}"])
            debug(output)
            return true
        end
    end

    def create
        output = Puppet::Util.execute(["lvcreate", "-L",
resource[:size], "-n", resource[:name], resource[:vg]])
        debug(output)
        return true
    end

    def destroy
        output = Puppet::Util.execute(["lvchange", "-an", "/dev/
#{resource[:vg]}/#{resource[:name]}"])
        output = Puppet::Util.execute(["lvremove", "-f", "/dev/
#{resource[:vg]}/#{resource[:name]}"])
        debug(output)
        return true
    end

    def exists?
        output = Puppet::Util.execute(["lvs", "--noheading", "/dev/
#{resource[:vg]}/#{resource[:name]}"], :failonfail => false, :combine
=> true)
        debug(output)
        if output.include?("One or more specified logical volume(s)
not found.")
            return nil
        else
            return true
        end
    end
end

Thanks,

Daniel

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/puppet-dev?hl=en.

Reply via email to