diff options
author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-10-17 21:38:30 +0000 |
---|---|---|
committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2006-10-17 21:38:30 +0000 |
commit | 95f2fe70bf63791fb691d539281f5cfbfd1fb664 (patch) | |
tree | bde480ce5ada8ea2abbc5fecf8f5c9aa3ca2aabf | |
parent | 86dae84dad4cd5688029c398109b15b6074cf3c4 (diff) | |
download | puppet-95f2fe70bf63791fb691d539281f5cfbfd1fb664.tar.gz puppet-95f2fe70bf63791fb691d539281f5cfbfd1fb664.tar.xz puppet-95f2fe70bf63791fb691d539281f5cfbfd1fb664.zip |
Ported mount over to using providers
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@1801 980ebf18-57e1-0310-9a29-db15c13687c0
-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 | ||||
-rw-r--r-- | test/lib/puppettest/fakes.rb | 30 | ||||
-rw-r--r-- | test/lib/puppettest/support/utils.rb | 13 | ||||
-rwxr-xr-x | test/providers/parsedmount.rb | 213 | ||||
-rwxr-xr-x | test/types/mount.rb | 274 |
11 files changed, 622 insertions, 482 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$ diff --git a/test/lib/puppettest/fakes.rb b/test/lib/puppettest/fakes.rb index f2d424295..40fe96a10 100644 --- a/test/lib/puppettest/fakes.rb +++ b/test/lib/puppettest/fakes.rb @@ -3,6 +3,7 @@ require 'puppettest' module PuppetTest # A baseclass for the faketypes. class FakeModel + include Puppet::Util class << self attr_accessor :name @name = :fakemodel @@ -29,7 +30,8 @@ module PuppetTest end def []=(param, value) - unless @realmodel.attrtype(param) + param = symbolize(param) + unless @realmodel.validattr?(param) raise Puppet::DevError, "Invalid attribute %s for %s" % [param, @realmodel.name] end @@ -46,7 +48,7 @@ module PuppetTest @is = {} @should = {} @params = {} - self[:name] = name + self[@realmodel.namevar] = name end def inspect @@ -121,6 +123,29 @@ module PuppetTest end end + class FakeParsedProvider < FakeProvider + def hash + ret = {} + instance_variables.each do |v| + v = v.sub("@", '') + if val = self.send(v) + ret[v.intern] = val + end + end + + return ret + end + + def store(hash) + hash.each do |n, v| + method = n.to_s + "=" + if respond_to? method + send(method, v) + end + end + end + end + @@fakemodels = {} @@fakeproviders = {} @@ -132,7 +157,6 @@ module PuppetTest end obj = @@fakemodels[type].new(name) - obj[:name] = name options.each do |name, val| obj[name] = val end diff --git a/test/lib/puppettest/support/utils.rb b/test/lib/puppettest/support/utils.rb index ea2d5483c..c7d54d5e6 100644 --- a/test/lib/puppettest/support/utils.rb +++ b/test/lib/puppettest/support/utils.rb @@ -142,6 +142,19 @@ module PuppetTest return comp end + + def setme + # retrieve the user name + id = %x{id}.chomp + if id =~ /uid=\d+\(([^\)]+)\)/ + @me = $1 + else + puts id + end + unless defined? @me + raise "Could not retrieve user name; 'id' did not work" + end + end end # $Id$ diff --git a/test/providers/parsedmount.rb b/test/providers/parsedmount.rb new file mode 100755 index 000000000..a4bcb7534 --- /dev/null +++ b/test/providers/parsedmount.rb @@ -0,0 +1,213 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet' +require 'facter' + +class TestParsedMounts < Test::Unit::TestCase + include PuppetTest + + def setup + super + @provider = Puppet.type(:mount).provider(:parsed) + + @oldfiletype = @provider.filetype + end + + def teardown + Puppet::FileType.filetype(:ram).clear + @provider.filetype = @oldfiletype + super + end + + def mkmountargs + mount = nil + + if defined? @pcount + @pcount += 1 + else + @pcount = 1 + end + args = { + :path => "/fspuppet%s" % @pcount, + :device => "/dev/dsk%s" % @pcount, + } + + @provider.fields.each do |field| + unless args.include? field + args[field] = "fake%s" % @pcount + end + end + + return args + end + + def mkmount + hash = mkmountargs() + #hash[:provider] = @provider.name + + fakemodel = fakemodel(:mount, hash[:path]) + + mount = @provider.new(fakemodel) + #mount = Puppet.type(:mount).create(hash) + + hash.each do |name, val| + fakemodel[name] = val + end + assert(mount, "Could not create provider mount") + + return mount + end + + # Here we just create a fake host type that answers to all of the methods + # but does not modify our actual system. + def mkfaketype + @provider.filetype = Puppet::FileType.filetype(:ram) + end + + def test_simplemount + mkfaketype + assert_nothing_raised { + assert_equal([], @provider.retrieve) + } + + # Now create a provider + mount = nil + assert_nothing_raised { + mount = mkmount + } + + # Make sure we're still empty + assert_nothing_raised { + assert_equal([], @provider.retrieve) + } + + hash = mount.model.to_hash + + # Try storing it + assert_nothing_raised do + mount.store(hash) + end + + # Make sure we get the mount back + assert_nothing_raised { + assert_equal([hash], @provider.retrieve) + } + + # Now remove the whole object + assert_nothing_raised { + mount.store({}) + assert_equal([], @provider.retrieve) + } + end + + unless Facter["operatingsystem"].value == "Darwin" + def test_mountsparse + fakedataparse(fake_fstab) do + # Now just make we've got some mounts we know will be there + hashes = @provider.retrieve.find_all { |i| i.is_a? Hash } + assert(hashes.length > 0, "Did not create any hashes") + root = hashes.find { |i| i[:path] == "/" } + assert(root, "Could not retrieve root mount") + end + end + + def test_rootfs + fs = nil + @provider.path = fake_fstab() + fakemodel = fakemodel(:mount, "/") + mount = @provider.new(fakemodel) + mount.model[:path] = "/" + assert(mount.hash, "Could not retrieve root fs") + + assert_nothing_raised { + assert(mount.mounted?, "Root is considered not mounted") + } + end + end + + if Puppet::SUIDManager.uid == 0 + def test_mountfs + fs = nil + case Facter["hostname"].value + when "culain": fs = "/ubuntu" + when "atalanta": fs = "/mnt" + when "figurehead": fs = "/cg4/net/depts" + else + $stderr.puts "No mount for mount testing; skipping" + return + end + + oldtext = @provider.fileobj.read + + ftype = @provider.filetype + + # Make sure the original gets reinstalled. + if ftype == Puppet::FileType.filetype(:netinfo) + cleanup do + IO.popen("niload -r /mounts .", "w") do |file| + file.puts oldtext + end + end + else + cleanup do + @provider.fileobj.write(oldtext) + end + end + + fakemodel = fakemodel(:mount, "/") + obj = @provider.new(fakemodel) + obj.model[:path] = fs + + current = nil + + assert_nothing_raised { + current = obj.mounted? + } + + if current + # Make sure the original gets reinstalled. + cleanup do + unless obj.mounted? + obj.mount + end + end + end + + unless current + assert_nothing_raised { + obj.mount + } + end + + assert_nothing_raised { + obj.unmount + } + assert(! obj.mounted?, "FS still mounted") + assert_nothing_raised { + obj.mount + } + assert(obj.mounted?, "FS not mounted") + + end + end + + def fake_fstab + os = Facter['operatingsystem'] + if os == "Solaris" + name = "solaris.fstab" + elsif os == "FreeBSD" + name = "freebsd.fstab" + else + # Catchall for other fstabs + name = "linux.fstab" + end + oldpath = @provider.path + cleanup do @provider.path = oldpath end + return fakefile(File::join("data/types/mount", name)) + end +end + +# $Id$ diff --git a/test/types/mount.rb b/test/types/mount.rb index 302e2376a..aab80506d 100755 --- a/test/types/mount.rb +++ b/test/types/mount.rb @@ -2,43 +2,64 @@ $:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ -# Test host job creation, modification, and destruction - require 'puppettest' require 'puppet' -require 'puppet/type/parsedtype/mount' -require 'facter' class TestMounts < Test::Unit::TestCase include PuppetTest + + p = Puppet::Type.type(:mount).provide :fake, :parent => PuppetTest::FakeParsedProvider do + @name = :fake + apimethods :ensure + + attr_accessor :mounted + + def create + @ensure = :present + end + + def delete + @ensure = :absent + @mounted = false + end + + def exists? + if defined? @ensure and @ensure == :present + true + else + false + end + end + + def mounted? + self.mounted + end + + def mount + self.mounted = true + end + + def unmount + self.mounted = false + end + end + + FakeMountProvider = p + + @@fakeproviders[:mount] = p + def setup super - @mounttype = Puppet.type(:mount) - @oldfiletype = @mounttype.filetype + @realprovider = Puppet::Type.type(:mount).defaultprovider + Puppet::Type.type(:mount).defaultprovider = FakeMountProvider end def teardown - @mounttype.filetype = @oldfiletype - Puppet.type(:file).clear + Puppet.type(:mount).clear + Puppet::Type.type(:mount).defaultprovider = nil super end - # Here we just create a fake host type that answers to all of the methods - # but does not modify our actual system. - def mkfaketype - pfile = tempfile() - old = @mounttype.filetype - @mounttype.filetype = Puppet::FileType.filetype(:ram) - - cleanup do - @mounttype.filetype = old - @mounttype.fileobj = nil - end - - # Reset this, just in case - @mounttype.fileobj = nil - end - def mkmount mount = nil @@ -52,7 +73,7 @@ class TestMounts < Test::Unit::TestCase :device => "/dev/dsk%s" % @pcount, } - Puppet.type(:mount).fields.each do |field| + @realprovider.fields.each do |field| unless args.include? field args[field] = "fake%s" % @pcount end @@ -66,178 +87,47 @@ class TestMounts < Test::Unit::TestCase end def test_simplemount - mkfaketype - host = nil - assert_nothing_raised { - assert_nil(Puppet.type(:mount).retrieve) - } - - mount = mkmount - + mount = nil + oldprv = Puppet.type(:mount).defaultprovider + Puppet.type(:mount).defaultprovider = nil assert_nothing_raised { - Puppet.type(:mount).store - } + Puppet.type(:mount).defaultprovider.retrieve - assert_nothing_raised { - assert( - Puppet.type(:mount).to_file.include?( - Puppet.type(:mount).fileobj.read - ), - "File does not include all of our objects" - ) - } - end - - unless Facter["operatingsystem"].value == "Darwin" - def test_mountsparse - use_fake_fstab - assert_nothing_raised { - @mounttype.retrieve - } - - # Now just make we've got some mounts we know will be there - root = @mounttype["/"] - assert(root, "Could not retrieve root mount") - end - - def test_rootfs - fs = nil - use_fake_fstab - assert_nothing_raised { - Puppet.type(:mount).retrieve - } - - assert_nothing_raised { - fs = Puppet.type(:mount)["/"] - } - assert(fs, "Could not retrieve root fs") - - assert_nothing_raised { - assert(fs.mounted?, "Root is considered not mounted") - } - end - end + count = 0 + Puppet.type(:mount).each do |h| + count += 1 + end - # Make sure it reads and writes correctly. - def test_readwrite - use_fake_fstab - assert_nothing_raised { - Puppet::Type.type(:mount).retrieve + assert_equal(0, count, "Found mounts in empty file somehow") } + Puppet.type(:mount).defaultprovider = oldprv - oldtype = Puppet::Type.type(:mount).filetype - - # Now switch to storing in ram - mkfaketype - - fs = mkmount - - assert(Puppet::Type.type(:mount).filetype != oldtype) - - assert_events([:mount_created], fs) - - text = Puppet::Type.type(:mount).fileobj.read - - assert(text =~ /#{fs[:path]}/, "Text did not include new fs") - - fs[:ensure] = :absent - - assert_events([:mount_removed], fs) - text = Puppet::Type.type(:mount).fileobj.read - - assert(text !~ /#{fs[:path]}/, "Text still includes new fs") - - fs[:ensure] = :present - - assert_events([:mount_created], fs) - - text = Puppet::Type.type(:mount).fileobj.read + mount = mkmount - assert(text =~ /#{fs[:path]}/, "Text did not include new fs") + assert_apply(mount) - fs[:options] = "rw,noauto" + assert_nothing_raised { mount.retrieve } - assert_events([:mount_changed], fs) + assert_equal(:mounted, mount.is(:ensure)) end - if Puppet::SUIDManager.uid == 0 + # Make sure fs mounting behaves appropriately. This is more a test of + # whether things get mounted and unmounted based on the value of 'ensure'. def test_mountfs - fs = nil - case Facter["hostname"].value - when "culain": fs = "/ubuntu" - when "atalanta": fs = "/mnt" - when "figurehead": fs = "/cg4/net/depts" - else - $stderr.puts "No mount for mount testing; skipping" - return - end - - assert_nothing_raised { - Puppet.type(:mount).retrieve - } - - oldtext = Puppet::Type.type(:mount).fileobj.read - - ftype = Puppet::Type.type(:mount).filetype - - # Make sure the original gets reinstalled. - if ftype == Puppet::FileType.filetype(:netinfo) - cleanup do - IO.popen("niload -r /mounts .", "w") do |file| - file.puts oldtext - end - end - else - cleanup do - Puppet::Type.type(:mount).fileobj.write(oldtext) - end - end - - obj = Puppet.type(:mount)[fs] + obj = mkmount - assert(obj, "Could not retrieve %s object" % fs) - - current = nil - - assert_nothing_raised { - current = obj.mounted? - } - - if current - # Make sure the original gets reinstalled. - cleanup do - unless obj.mounted? - obj.mount - end - end - end - - unless current - assert_nothing_raised { - obj.mount - } - end - - # Now copy all of the states' "is" values to the "should" values - obj.each do |state| - state.should = state.is - end + assert_apply(obj) # Verify we can remove the mount assert_nothing_raised { obj[:ensure] = :absent } - assert_events([:mount_removed], obj) + assert_events([:mount_deleted], obj) assert_events([], obj) # And verify it's gone - assert(!obj.mounted?, "Object is mounted after being removed") - - text = Puppet.type(:mount).fileobj.read - - assert(text !~ /#{fs}/, - "Fstab still contains %s" % fs) + assert(!obj.provider.mounted?, "Object is mounted after being removed") assert_nothing_raised { obj[:ensure] = :present @@ -246,10 +136,7 @@ class TestMounts < Test::Unit::TestCase assert_events([:mount_created], obj) assert_events([], obj) - text = Puppet::Type.type(:mount).fileobj.read - assert(text =~ /#{fs}/, "Fstab does not contain %s" % fs) - - assert(! obj.mounted?, "Object is mounted incorrectly") + assert(! obj.provider.mounted?, "Object is mounted incorrectly") assert_nothing_raised { obj[:ensure] = :mounted @@ -258,33 +145,8 @@ class TestMounts < Test::Unit::TestCase assert_events([:mount_mounted], obj) assert_events([], obj) - text = Puppet::Type.type(:mount).fileobj.read - assert(text =~ /#{fs}/, - "Fstab does not contain %s" % fs) - obj.retrieve - assert(obj.mounted?, "Object is not mounted") - - unless current - assert_nothing_raised { - obj.unmount - } - end - end - end - - def use_fake_fstab - os = Facter['operatingsystem'] - if os == "Solaris" - name = "solaris.fstab" - elsif os == "FreeBSD" - name = "freebsd.fstab" - else - # Catchall for other fstabs - name = "linux.fstab" - end - fstab = fakefile(File::join("data/types/mount", name)) - Puppet::Type.type(:mount).path = fstab + assert(obj.provider.mounted?, "Object is not mounted") end end |