summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/package/aix.rb
blob: 5cccdf376ca494a8512170d3773c4f97a0d23daf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
require 'puppet/provider/package'
require 'puppet/util/package'

Puppet::Type.type(:package).provide :aix, :parent => Puppet::Provider::Package do
    desc "Installation from AIX Software directory"

    # The commands we are using on an AIX box are installed standard
    # (except nimclient) nimclient needs the bos.sysmgt.nim.client fileset.
    commands    :lslpp => "/usr/bin/lslpp",
                :installp => "/usr/sbin/installp"

    # AIX supports versionable packages with and without a NIM server
    has_feature :versionable

    confine  :operatingsystem => [ :aix ]
    defaultfor :operatingsystem => :aix

    attr_accessor   :latest_info

    def self.srclistcmd(source)
        return [ command(:installp), "-L", "-d", source ]
    end

    def self.prefetch(packages)
        if Process.euid != 0
            raise Puppet::Error, "The aix provider can only be used by root"
        end

        return unless packages.detect { |name, package| package.should(:ensure) == :latest }

        sources = packages.collect { |name, package| package[:source] }.uniq

        updates = {}
        sources.each do |source|
            execute(self.srclistcmd(source)).each do |line|
                if line =~ /^[^#][^:]*:([^:]*):([^:]*)/
                    current = {}
                    current[:name]    = $1
                    current[:version] = $2
                    current[:source]  = source

                    if updates.key?(current[:name])
                        previous = updates[current[:name]]

                        unless Puppet::Util::Package.versioncmp(previous[:version], current[:version]) == 1
                            updates[ current[:name] ] = current 
                        end

                    else
                        updates[current[:name]] = current
                    end
                end
            end
        end

        packages.each do |name, package|
            if info = updates[package[:name]]
                package.provider.latest_info = info[0]
            end
        end
    end

    def uninstall
        # Automatically process dependencies when installing/uninstalling
        # with the -g option to installp.
        installp "-gu", @resource[:name]
    end

    def install(useversion = true)
        unless source = @resource[:source]
            self.fail "A directory is required which will be used to find packages"
        end

        pkg = @resource[:name]

        if (! @resource.should(:ensure).is_a? Symbol) and useversion
            pkg << " #{@resource.should(:ensure)}"
        end

        installp "-acgwXY", "-d", source, pkg
    end

    def self.pkglist(hash = {})
        cmd = [command(:lslpp), "-qLc"]

        if name = hash[:pkgname]
            cmd << name
        end

        begin
            list = execute(cmd).scan(/^[^#][^:]*:([^:]*):([^:]*)/).collect { |n,e|
                { :name => n, :ensure => e, :provider => self.name }
            }
        rescue Puppet::ExecutionFailure => detail
            if hash[:pkgname]
                return nil
            else
                raise Puppet::Error, "Could not list installed Packages: %s" % detail
            end
        end

        if hash[:pkgname]
            return list.shift
        else
            return list
        end
    end

    def self.instances
        pkglist.collect do |hash|
            new(hash)
        end
    end

    def latest
        upd = latest_info

        unless upd.nil?
            return "#{upd[:version]}"
        else
            if properties[:ensure] == :absent
                raise Puppet::DevError, "Tried to get latest on a missing package"
            end

            return properties[:ensure]
        end
    end

    def query
        return self.class.pkglist(:pkgname => @resource[:name])
    end

    def update
        self.install(false)
    end
end