summaryrefslogtreecommitdiffstats
path: root/lib/puppet/provider/package/aix.rb
blob: 134a845264273ce94670153f5276f8d928a7e6db (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
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)
    [ command(:installp), "-L", "-d", source ]
  end

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

    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]]

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

          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]

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

    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: #{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
      raise Puppet::DevError, "Tried to get latest on a missing package" if properties[:ensure] == :absent

      return properties[:ensure]
    end
  end

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

  def update
    self.install(false)
  end
end