diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-09-05 01:03:57 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-09-05 01:03:57 +0000 |
commit | b43b489073beb01da9b4de501d3c019326d97961 (patch) | |
tree | 58264a9554ca1e71f5441fb3703fb798cb71a6eb /lib | |
parent | 639ed3d75380dc59e05bb38c920f18836fd12913 (diff) | |
download | puppet-b43b489073beb01da9b4de501d3c019326d97961.tar.gz puppet-b43b489073beb01da9b4de501d3c019326d97961.tar.xz puppet-b43b489073beb01da9b4de501d3c019326d97961.zip |
Committing functional mount support. All that's left in this chunk of work is cron.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1552 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/puppet/provider/mount/parsed.rb | 171 | ||||
-rw-r--r-- | lib/puppet/statechange.rb | 8 | ||||
-rw-r--r-- | lib/puppet/transaction.rb | 2 | ||||
-rwxr-xr-x | lib/puppet/type/mount.rb | 117 | ||||
-rwxr-xr-x | lib/puppet/type/parsedtype.rb | 27 | ||||
-rwxr-xr-x | lib/puppet/type/parsedtype/mount.rb | 271 | ||||
-rw-r--r-- | lib/puppet/type/state.rb | 16 |
7 files changed, 310 insertions, 302 deletions
diff --git a/lib/puppet/provider/mount/parsed.rb b/lib/puppet/provider/mount/parsed.rb new file mode 100755 index 000000000..b768d6c5e --- /dev/null +++ b/lib/puppet/provider/mount/parsed.rb @@ -0,0 +1,171 @@ +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] + @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 + + confine :exists => @path + + 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 = @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 + + 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/statechange.rb b/lib/puppet/statechange.rb index 84af4f8da..d11a985fe 100644 --- a/lib/puppet/statechange.rb +++ b/lib/puppet/statechange.rb @@ -48,10 +48,12 @@ module Puppet # Generate an appropriate event from the is/should values. def genevent tail = if @state.name == :ensure - if @is == :absent - "created" + if @should == :present + "created" + elsif @should == :absent + "deleted" else - "deleted" + @should.to_s end else "changed" diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index f38d7cbbd..d947afbf2 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -99,7 +99,7 @@ class Transaction }.flatten.reject { |e| e.nil? } # If our child responds to a 'flush' method, call it. - if child.respond_to? :flush + if childevents.length > 0 and child.respond_to? :flush begin child.flush rescue => detail diff --git a/lib/puppet/type/mount.rb b/lib/puppet/type/mount.rb new file mode 100755 index 000000000..641ff8592 --- /dev/null +++ b/lib/puppet/type/mount.rb @@ -0,0 +1,117 @@ +require 'puppet/type/parsedtype' + +module Puppet + newtype(:mount, Puppet::Type::ParsedType) do + newstate(:ensure) 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 + + # The default method doesn't, um, do anything, since it's all + # done in the flush at the end. + #def sync(value) + # set(value) + #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.rb b/lib/puppet/type/parsedtype.rb index 86d66043d..9d37adf17 100755 --- a/lib/puppet/type/parsedtype.rb +++ b/lib/puppet/type/parsedtype.rb @@ -58,9 +58,13 @@ module Puppet # If the ensure state is out of sync, it will always be called # first, so I don't need to worry about that. def sync(value) - # Just copy the value to our 'is' state; it'll get flushed later - #self.is = value - + # We only pass through to the parent method if there are values + # defined. Otherwise, there's no work to do, since all of the + # work is done in the flush. + if self.class.values and ! self.class.values.empty? + super(value) + end + # The value gets flushed later. return nil end end @@ -132,19 +136,21 @@ module Puppet def self.postinit unless validstate? :ensure newstate(:ensure) do - newvalue(:present, :event => :host_created) do - @parent.create + newvalue(:present) do + # The value will get flushed appropriately + return nil end - newvalue(:absent, :event => :host_deleted) do - @parent.destroy + newvalue(:absent) do + # The value will get flushed appropriately + return nil end defaultto do if @parent.managed? :present else - :absent + nil end end end @@ -199,9 +205,4 @@ module Puppet end end -#require 'puppet/type/parsedtype/host' -#require 'puppet/type/parsedtype/port' -require 'puppet/type/parsedtype/mount' -#require 'puppet/type/parsedtype/sshkey' - # $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$ diff --git a/lib/puppet/type/state.rb b/lib/puppet/type/state.rb index b4b773eb9..e186c401d 100644 --- a/lib/puppet/type/state.rb +++ b/lib/puppet/type/state.rb @@ -258,13 +258,7 @@ class State < Puppet::Parameter end # Call the method associated with a given value. - def set - if self.insync? - self.log "already in sync" - return nil - end - - value = self.should + def set(value) method = "set_" + value.to_s event = nil if self.respond_to?(method) @@ -362,19 +356,13 @@ class State < Puppet::Parameter value = self.should end - if self.insync? - self.info "already in sync" - return :nochange - #else - #self.info "%s vs %s" % [self.is.inspect, self.should.inspect] - end unless self.class.values self.devfail "No values defined for %s" % self.class.name end # Set ourselves to whatever our should value is. - self.set + self.set(value || self.should) end def to_s |