# Manage NetInfo POSIX objects. Probably only used on OS X, but I suppose # it could be used elsewhere. require 'puppet' require 'puppet/provider/nameservice' class Puppet::Provider::NameService class NetInfo < Puppet::Provider::NameService class << self attr_writer :netinfodir end # We have to initialize manually because we're not using # classgen() here. initvars() commands :lookupd => "/usr/sbin/lookupd" # Attempt to flush the database, but this doesn't seem to work at all. def self.flush begin lookupd "-flushcache" rescue Puppet::ExecutionFailure # Don't throw an error; it's just a failed cache flush Puppet.err "Could not flush lookupd cache: %s" % output end end # Similar to posixmethod, what key do we use to get data? Defaults # to being the object name. def self.netinfodir if defined? @netinfodir return @netinfodir else return @resource_type.name.to_s + "s" end end def self.finish case self.name when :uid: noautogen when :gid: noautogen end end def self.instances report(@resource_type.validproperties).collect do |hash| self.new(hash) end end # Convert a NetInfo line into a hash of data. def self.line2hash(line, params) values = line.split(/\t/) hash = {} params.zip(values).each do |param, value| next if value == '#NoValue#' hash[param] = if value =~ /^[-0-9]+$/ Integer(value) else value end end hash end # What field the value is stored under. def self.netinfokey(name) name = symbolize(name) self.option(name, :key) || name end # Retrieve the data, yo. # FIXME This should retrieve as much information as possible, # rather than retrieving it one at a time. def self.report(*params) dir = self.netinfodir() cmd = [command(:nireport), "/", "/%s" % dir] params.flatten! # We require the name in order to know if we match. There's no # way to just report on our individual object, we have to get the # whole list. params.unshift :name unless params.include? :name params.each do |param| if key = netinfokey(param) cmd << key.to_s else raise Puppet::DevError, "Could not find netinfokey for property %s" % self.class.name end end begin output = execute(cmd) rescue Puppet::ExecutionFailure => detail Puppet.err "Failed to call nireport: %s" % detail return nil end return output.split("\n").collect { |line| line2hash(line, params) } end # How to add an object. def addcmd creatorcmd("-create") end def creatorcmd(arg) cmd = [command(:niutil)] cmd << arg cmd << "/" << "/%s/%s" % [self.class.netinfodir(), @resource[:name]] return cmd end def deletecmd creatorcmd("-destroy") end def destroy delete() end def ensure=(arg) super # Because our stupid type can't create the whole thing at once, # we have to do this hackishness. Yay. if arg == :present @resource.class.validproperties.each do |name| next if name == :ensure next unless val = @resource.should(name) || autogen(name) self.send(name.to_s + "=", val) end end end # Retrieve a specific value by name. def get(param) hash = getinfo(false) if hash return hash[param] else return :absent end end # Retrieve everything about this object at once, instead of separately. def getinfo(refresh = false) if refresh or (! defined? @infohash or ! @infohash) properties = [:name] + self.class.resource_type.validproperties properties.delete(:ensure) if properties.include? :ensure @infohash = single_report(*properties) end return @infohash end def modifycmd(param, value) cmd = [command(:niutil)] # if value.is_a?(Array) # warning "Netinfo providers cannot currently handle multiple values" # end cmd << "-createprop" << "/" << "/%s/%s" % [self.class.netinfodir, @resource[:name]] value = [value] unless value.is_a?(Array) if key = netinfokey(param) cmd << key cmd += value else raise Puppet::DevError, "Could not find netinfokey for property %s" % self.class.name end cmd end # Determine the flag to pass to our command. def netinfokey(name) self.class.netinfokey(name) end # Get a report for a single resource, not the whole table def single_report(*properties) self.class.report(*properties).find do |hash| hash[:name] == self.name end end def setuserlist(group, list) cmd = [command(:niutil), "-createprop", "/", "/groups/%s" % group, "users", list.join(",")] begin output = execute(cmd) rescue Puppet::ExecutionFailure => detail raise Puppet::Error, "Failed to set user list on %s: %s" % [group, detail] end end end end # $Id: netinfo.rb 2552 2007-06-05 01:17:00Z luke $