diff options
Diffstat (limited to 'lib/puppet')
-rw-r--r-- | lib/puppet/metatype/attributes.rb | 1 | ||||
-rw-r--r-- | lib/puppet/metatype/providers.rb | 2 | ||||
-rw-r--r-- | lib/puppet/provider.rb | 11 | ||||
-rwxr-xr-x | lib/puppet/provider/mount/parsed.rb | 174 | ||||
-rwxr-xr-x | lib/puppet/type/host.rb | 2 | ||||
-rwxr-xr-x | lib/puppet/type/mount.rb | 113 | ||||
-rwxr-xr-x | lib/puppet/type/parsedtype/mount.rb | 271 |
7 files changed, 301 insertions, 273 deletions
diff --git a/lib/puppet/metatype/attributes.rb b/lib/puppet/metatype/attributes.rb index d647e174f..764aba8ee 100644 --- a/lib/puppet/metatype/attributes.rb +++ b/lib/puppet/metatype/attributes.rb @@ -304,6 +304,7 @@ class Puppet::Type def self.validattr?(name) name = symbolize(name) + return true if name == :name @validattrs ||= {} unless @validattrs.include?(name) diff --git a/lib/puppet/metatype/providers.rb b/lib/puppet/metatype/providers.rb index ab7371f10..c59b7f84a 100644 --- a/lib/puppet/metatype/providers.rb +++ b/lib/puppet/metatype/providers.rb @@ -167,7 +167,7 @@ class Puppet::Type provider.suitable? }.collect { |name, provider| provider - } + }.reject { |p| p.name == :fake } # For testing end def provider=(name) diff --git a/lib/puppet/provider.rb b/lib/puppet/provider.rb index 88a7ba8a6..e0f465159 100644 --- a/lib/puppet/provider.rb +++ b/lib/puppet/provider.rb @@ -7,6 +7,7 @@ class Puppet::Provider class << self # Include the util module so we have access to things like 'binary' include Puppet::Util, Puppet::Util::Docs + include Puppet::Util::Logging attr_accessor :name, :model attr_writer :doc end @@ -127,15 +128,18 @@ class Puppet::Provider when :exists: values.each do |value| unless value and FileTest.exists? value + debug "Not suitable: missing %s" % value return false end end when :true: values.each do |v| + debug "Not suitable: false value" return false unless v end when :false: values.each do |v| + debug "Not suitable: true value" return false if v end else # Just delegate everything else to facter @@ -145,6 +149,7 @@ class Puppet::Provider found = values.find do |v| result == v.to_s.downcase.intern end + debug "Not suitable: %s not in %s" [check, values] return false unless found else return false @@ -155,6 +160,12 @@ class Puppet::Provider return true end + def self.to_s + unless defined? @str + @str = "%s provider %s" % [@model.name, self.name] + end + end + dochook(:defaults) do if @defaults.length > 0 return " Default for " + @defaults.collect do |f, v| diff --git a/lib/puppet/provider/mount/parsed.rb b/lib/puppet/provider/mount/parsed.rb new file mode 100755 index 000000000..5e9a6cf1d --- /dev/null +++ b/lib/puppet/provider/mount/parsed.rb @@ -0,0 +1,174 @@ +require 'puppet/provider/parsedfile' + +Puppet::Type.type(:mount).provide :parsed, :parent => Puppet::Provider::ParsedFile do + @filetype = Puppet::FileType.filetype(:flat) + + commands :mount => "mount", :umount => "umount", :df => "df" + + def self.init + @platform = Facter["operatingsystem"].value + case @platform + when "Solaris": + @path = "/etc/vfstab" + @fields = [:device, :blockdevice, :path, :fstype, :pass, :atboot, + :options] + @fielddefaults = [ nil ] * @fields.size + when "Darwin": + @filetype = Puppet::FileType.filetype(:netinfo) + @filetype.format = "fstab" + @path = "mounts" + @fields = [:device, :path, :fstype, :options, :dump, :pass] + @fielddefaults = [ nil ] * @fields.size + + # How to map the dumped table to what we want + @fieldnames = { + "name" => :device, + "dir" => :path, + "dump_freq" => :dump, + "passno" => :pass, + "vfstype" => :fstype, + "opts" => :options + } + else + @path = "/etc/fstab" + @fields = [:device, :path, :fstype, :options, :dump, :pass] + @fielddefaults = [ nil ] * 4 + [ "0", "2" ] + end + + # Allow Darwin to override the default filetype + unless defined? @filetype + @filetype = Puppet::FileType.filetype(:flat) + end + end + + init + + # XXX This needs to change to being a netinfo provider + unless @platform == "Darwin" + confine :exists => @path + end + + def self.clear + init + super + end + + # Parse a mount tab. + # + # This method also stores existing comments, and it stores all + # mounts in order, mostly so that comments are retained in the + # order they were written and in proximity to the same fses. + def self.parse(text) + # provide a single exception for darwin & netinfo + if @filetype == Puppet::FileType.filetype(:netinfo) + return parseninfo(text) + end + count = 0 + + instances = [] + text.chomp.split("\n").each { |line| + hash = {} + case line + when /^#/, /^\s*$/: + # add comments and blank lines to the list as they are + instances << line + comment(line) + else + values = line.split(/\s+/) + if @fields.length < values.length + raise Puppet::Error, "Could not parse line %s" % line + end + + values = @fielddefaults.zip(values).collect { |d, v| v || d } + unless @fields.length == values.length + raise Puppet::Error, "Could not parse line %s" % line + end + + @fields.zip(values).each do |field, value| + hash[field] = value + end + + instances << hash + count += 1 + end + } + + return instances + end + + # Parse a netinfo table. + def self.parseninfo(text) + array = @fileobj.to_array(text) + + instances = [] + array.each do |record| + hash = {} + @fieldnames.each do |name, field| + if value = record[name] + if field == :options + hash[field] = value.join(",") + else + hash[field] = value[0] + end + else + raise ArgumentError, "Field %s was not provided" % [name] + end + end + + instances << hash + end + + return instances + end + + # Convert the current object into an fstab-style string. + def self.to_record(hash) + self.fields.collect do |field| + if value = hash[field] + value + else + raise Puppet::Error, + "Could not retrieve value for %s" % field + end + end.join("\t") + end + + # This only works when the mount point is synced to the fstab. + def mount + output = %x{#{command(:mount)} #{@model[:path]} 2>&1} + + unless $? == 0 + raise Puppet::Error, "Could not mount %s: %s" % [@model[:path], output] + end + end + + # This only works when the mount point is synced to the fstab. + def unmount + output = %x{#{command(:umount)} #{@model[:path]}} + + unless $? == 0 + raise Puppet::Error, "Could not unmount %s" % @model[:path] + end + end + + # Is the mount currently mounted? + def mounted? + platform = Facter["operatingsystem"].value + df = command(:df) + case Facter["operatingsystem"].value + # Solaris's df prints in a very weird format + when "Solaris": df = "#{command(:df)} -k" + end + %x{#{df}}.split("\n").find do |line| + fs = line.split(/\s+/)[-1] + if platform == "Darwin" + fs == "/private/var/automount" + @model[:path] or + fs == @model[:path] + else + fs == @model[:path] + end + end + end +end + +# $Id$ diff --git a/lib/puppet/type/host.rb b/lib/puppet/type/host.rb index d68fe25a2..b2ed848fc 100755 --- a/lib/puppet/type/host.rb +++ b/lib/puppet/type/host.rb @@ -3,7 +3,7 @@ require 'puppet/type/parsedtype' module Puppet newtype(:host, Puppet::Type::ParsedType) do newstate(:ip) do - desc "The host's IP address." + desc "The host's IP address, IPv4 or IPv6." end newstate(:alias) do diff --git a/lib/puppet/type/mount.rb b/lib/puppet/type/mount.rb new file mode 100755 index 000000000..b92ab735b --- /dev/null +++ b/lib/puppet/type/mount.rb @@ -0,0 +1,113 @@ +require 'puppet/type/parsedtype' + +module Puppet + newtype(:mount, Puppet::Type::ParsedType) do + # Use the normal parent class, because we actually want to + # call code when sync() is called. + newstate(:ensure, :parent => Puppet::State) do + desc "Control what to do with this mount. If the value is + ``present``, the mount is entered into the mount table, + but not mounted, if it is ``absent``, the entry is removed + from the mount table and the filesystem is unmounted if + currently mounted, if it is ``mounted``, the filesystem + is entered into the mount table and mounted." + + newvalue(:present, :event => :mount_created) do + end + + newvalue(:absent, :event => :mount_deleted) do + if provider.mounted? + provider.unmount + end + end + + newvalue(:mounted, :event => :mount_mounted) do + # We have to flush any changes to disk. + @parent.flush + + provider.mount + end + + defaultto do + if @parent.managed? + :mounted + else + nil + end + end + + def retrieve + if provider.mounted? + return :mounted + else + val = super() + return val + end + end + end + + newstate(:device) do + desc "The device providing the mount. This can be whatever + device is supporting by the mount, including network + devices or devices specified by UUID rather than device + path, depending on the operating system." + end + + # Solaris specifies two devices, not just one. + newstate(:blockdevice) do + desc "The the device to fsck. This is state is only valid + on Solaris, and in most cases will default to the correct + value." + + # Default to the device but with "dsk" replaced with "rdsk". + defaultto do + if Facter["operatingsystem"].value == "Solaris" + device = @parent.value(:device) + if device =~ %r{/dsk/} + device.sub(%r{/dsk/}, "/rdsk/") + else + nil + end + else + nil + end + end + end + + newstate(:fstype) do + desc "The mount type. Valid values depend on the + operating system." + end + + newstate(:options) do + desc "Mount options for the mounts, as they would + appear in the fstab." + end + + newstate(:pass) do + desc "The pass in which the mount is checked." + end + + newstate(:atboot) do + desc "Whether to mount the mount at boot. Not all platforms + support this." + end + + newstate(:dump) do + desc "Whether to dump the mount. Not all platforms + support this." + end + + newparam(:path) do + desc "The mount path for the mount." + + isnamevar + end + + @doc = "Manages mounted mounts, including putting mount + information into the mount table. The actual behavior depends + on the value of the 'ensure' parameter." + end +end + +# $Id$ diff --git a/lib/puppet/type/parsedtype/mount.rb b/lib/puppet/type/parsedtype/mount.rb deleted file mode 100755 index 3f186ddca..000000000 --- a/lib/puppet/type/parsedtype/mount.rb +++ /dev/null @@ -1,271 +0,0 @@ -require 'etc' -require 'facter' -require 'puppet/type/parsedtype' -require 'puppet/type/state' - -module Puppet - newtype(:mount, Puppet::Type::ParsedType) do - ensurable do - desc "Control what to do with this mount. If the value is - ``present``, the mount is entered into the mount table, - but not mounted, if it is ``absent``, the entry is removed - from the mount table and the filesystem is unmounted if - currently mounted, if it is ``mounted``, the filesystem - is entered into the mount table and mounted." - - newvalue(:present) do - @parent.create() - end - - newvalue(:absent) do - @parent.destroy() - - if @parent.mounted? - @parent.unmount - end - - :mount_removed - end - - newvalue(:mounted) do - if @is == :absent - set_present - end - - @parent.mount - - :mount_mounted - end - - def retrieve - if @parent.mounted? - @is = :mounted - else - val = super() - @is = val - end - end - end - - newstate(:device) do - desc "The device providing the mount. This can be whatever - device is supporting by the mount, including network - devices or devices specified by UUID rather than device - path, depending on the operating system." - end - - # Solaris specifies two devices, not just one. - newstate(:blockdevice) do - desc "The the device to fsck. This is state is only valid - on Solaris, and in most cases will default to the correct - value." - - # Default to the device but with "dsk" replaced with "rdsk". - defaultto do - if Facter["operatingsystem"].value == "Solaris" - device = @parent.value(:device) - if device =~ %r{/dsk/} - device.sub(%r{/dsk/}, "/rdsk/") - else - nil - end - else - nil - end - end - end - - newstate(:fstype) do - desc "The mount type. Valid values depend on the - operating system." - end - - newstate(:options) do - desc "Mount options for the mounts, as they would - appear in the fstab." - end - - newstate(:pass) do - desc "The pass in which the mount is checked." - end - - newstate(:atboot) do - desc "Whether to mount the mount at boot. Not all platforms - support this." - end - - newstate(:dump) do - desc "Whether to dump the mount. Not all platforms - support this." - end - - newparam(:path) do - desc "The mount path for the mount." - - isnamevar - end - - @doc = "Manages mounted mounts, including putting mount - information into the mount table. The actual behavior depends - on the value of the 'ensure' parameter." - - def self.init - @platform = Facter["operatingsystem"].value - case @platform - when "Solaris": - @path = "/etc/vfstab" - @fields = [:device, :blockdevice, :path, :fstype, :pass, :atboot, - :options] - @defaults = [ nil ] * @fields.size - when "Darwin": - @filetype = Puppet::FileType.filetype(:netinfo) - @filetype.format = "fstab" - @path = "mounts" - @fields = [:device, :path, :fstype, :options, :dump, :pass] - @defaults = [ nil ] * @fields.size - - # How to map the dumped table to what we want - @fieldnames = { - "name" => :device, - "dir" => :path, - "dump_freq" => :dump, - "passno" => :pass, - "vfstype" => :fstype, - "opts" => :options - } - else - @path = "/etc/fstab" - @fields = [:device, :path, :fstype, :options, :dump, :pass] - @defaults = [ nil ] * 4 + [ "0", "2" ] - end - - # Allow Darwin to override the default filetype - unless defined? @filetype - @filetype = Puppet::FileType.filetype(:flat) - end - end - - init - - def self.clear - init - super - end - - # Parse a mount tab. - # - # This method also stores existing comments, and it stores all - # mounts in order, mostly so that comments are retained in the - # order they were written and in proximity to the same fses. - def self.parse(text) - # provide a single exception for darwin & netinfo - if @filetype == Puppet::FileType.filetype(:netinfo) - parseninfo(text) - return - end - count = 0 - hash = {} - text.chomp.split("\n").each { |line| - case line - when /^#/, /^\s*$/: - # add comments and blank lines to the list as they are - comment(line) - else - values = line.split(/\s+/) - if @fields.length < values.length - raise Puppet::Error, "Could not parse line %s" % line - end - - values = @defaults.zip(values).collect { |d, v| v || d } - unless @fields.length == values.length - raise Puppet::Error, "Could not parse line %s" % line - end - - @fields.zip(values).each do |field, value| - hash[field] = value - end - - hash2obj(hash) - - hash.clear - count += 1 - end - } - end - - # Parse a netinfo table. - def self.parseninfo(text) - array = @fileobj.to_array(text) - - hash = {} - array.each do |record| - @fieldnames.each do |name, field| - if value = record[name] - if field == :options - hash[field] = value.join(",") - else - hash[field] = value[0] - end - else - raise ArgumentError, "Field %s was not provided" % [name] - end - end - - - hash2obj(hash) - hash.clear - end - end - - # This only works when the mount point is synced to the fstab. - def mount - output = %x{mount #{self[:path]} 2>&1} - - unless $? == 0 - raise Puppet::Error, "Could not mount %s: %s" % [self[:path], output] - end - end - - # This only works when the mount point is synced to the fstab. - def unmount - output = %x{umount #{self[:path]}} - - unless $? == 0 - raise Puppet::Error, "Could not mount %s" % self[:path] - end - end - - # Is the mount currently mounted? - def mounted? - platform = Facter["operatingsystem"].value - df = "df" - case Facter["operatingsystem"].value - # Solaris's df prints in a very weird format - when "Solaris": df = "df -k" - end - %x{#{df}}.split("\n").find do |line| - fs = line.split(/\s+/)[-1] - if platform == "Darwin" - fs == "/private/var/automount" + self[:path] or - fs == self[:path] - else - fs == self[:path] - end - end - end - - # Convert the current object into an fstab-style string. - def to_record - self.class.fields.collect do |field| - if value = self.value(field) - value - else - raise Puppet::Error, - "Could not retrieve value for %s" % field - end - end.join("\t") - end - end -end - -# $Id$ |