diff --git a/lib/puppet/provider/mount.rb b/lib/puppet/provider/mount.rb index 81d93b5c1..354ddb16d 100644 --- a/lib/puppet/provider/mount.rb +++ b/lib/puppet/provider/mount.rb @@ -1,95 +1,53 @@ # Created by Luke Kanies on 2006-11-12. # Copyright (c) 2006. All rights reserved. require 'puppet' # A module just to store the mount/unmount methods. Individual providers # still need to add the mount commands manually. module Puppet::Provider::Mount - def mount - # Make sure the fstab file & entry exists - create - - if correctly_mounted? - # Nothing to do! - else - if anything_mounted? - unmount - - # We attempt to create the mount point here, because unmounting - # certain file systems/devices can cause the mount point to be - # deleted - ::FileUtils.mkdir_p(resource[:name]) - end - - mount! - end - end - # This only works when the mount point is synced to the fstab. - def mount! + def mount # Manually pass the mount options in, since some OSes *cough*OS X*cough* don't # read from /etc/fstab but still want to use this type. args = [] args << "-o" << self.options if self.options and self.options != :absent args << resource[:name] flush if respond_to?(:flush) mountcmd(*args) end def remount info "Remounting" if resource[:remounts] == :true mountcmd "-o", "remount", resource[:name] else unmount mount end end # This only works when the mount point is synced to the fstab. def unmount umount resource[:name] end - # Is anything currently mounted at this point? - def anything_mounted? + # Is the mount currently mounted? + def mounted? platform = Facter.value("operatingsystem") name = resource[:name] mounts = mountcmd.split("\n").find do |line| case platform when "Darwin" line =~ / on #{name} / or line =~ %r{ on /private/var/automount#{name}} when "Solaris", "HP-UX" - # Yes, Solaris does list mounts as "mount_point on device" line =~ /^#{name} on / when "AIX" line.split(/\s+/)[2] == name else line =~ / on #{name} / end end end - - # Is the desired thing mounted at this point? - def correctly_mounted? - platform = Facter.value("operatingsystem") - name = resource[:name] - device = resource[:device] - mounts = mountcmd.split("\n").find do |line| - case platform - when "Darwin" - line =~ /^#{device} on #{name} / or line =~ %r{^#{device} on /private/var/automount#{name}} - when "Solaris", "HP-UX" - # Yes, Solaris does list mounts as "mount_point on device" - line =~ /^#{name} on #{device}/ - when "AIX" - line.split(/\s+/)[2] == name && - line.split(/\s+/)[1] == device - else - line =~ /^#{device} on #{name} / - end - end - end end diff --git a/lib/puppet/type/mount.rb b/lib/puppet/type/mount.rb index 10eed5373..da9a70bdf 100755 --- a/lib/puppet/type/mount.rb +++ b/lib/puppet/type/mount.rb @@ -1,219 +1,224 @@ module Puppet # We want the mount to refresh when it changes. newtype(:mount, :self_refresh => true) do @doc = "Manages mounted filesystems, including putting mount information into the mount table. The actual behavior depends on the value of the 'ensure' parameter. Note that if a `mount` receives an event from another resource, it will try to remount the filesystems if `ensure` is set to `mounted`." feature :refreshable, "The provider can remount the filesystem.", :methods => [:remount] # Use the normal parent class, because we actually want to # call code when sync is called. newproperty(:ensure) do desc "Control what to do with this mount. Set this attribute to `umounted` to make sure the filesystem is in the filesystem table but not mounted (if the filesystem is currently mounted, it will be unmounted). Set it to `absent` to unmount (if necessary) and remove the filesystem from the fstab. Set to `mounted` to add it to the fstab and mount it. Set to `present` to add to fstab but not change mount/unmount status" newvalue(:defined) do provider.create return :mount_created end aliasvalue :present, :defined newvalue(:unmounted) do - if provider.anything_mounted? + if provider.mounted? syncothers provider.unmount return :mount_unmounted else provider.create return :mount_created end end newvalue(:absent, :event => :mount_deleted) do - provider.unmount if provider.anything_mounted? + provider.unmount if provider.mounted? provider.destroy end newvalue(:mounted, :event => :mount_mounted) do + # Create the mount point if it does not already exist. + current_value = self.retrieve + provider.create if current_value.nil? or current_value == :absent + syncothers - provider.mount + # The fs can be already mounted if it was absent but mounted + provider.mount unless provider.mounted? end def insync?(is) if should == :defined and is != :absent true else super end end def retrieve # We need to special case :mounted; if we're absent, we still # want curval = super() if curval == :absent return :absent - elsif provider.correctly_mounted? + elsif provider.mounted? return :mounted else return :unmounted end end def syncothers # We have to flush any changes to disk. currentvalues = @resource.retrieve_resource # Determine if there are any out-of-sync properties. oos = @resource.send(:properties).find_all do |prop| unless currentvalues.include?(prop) raise Puppet::DevError, "Parent has property %s but it doesn't appear in the current values", [prop.name] end if prop.name == :ensure false else ! prop.safe_insync?(currentvalues[prop]) end end.each { |prop| prop.sync }.length @resource.flush if oos > 0 end end newproperty(: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. newproperty(:blockdevice) do desc "The device to fsck. This is property 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 = @resource.value(:device) if device =~ %r{/dsk/} device.sub(%r{/dsk/}, "/rdsk/") else nil end else nil end end end newproperty(:fstype) do desc "The mount type. Valid values depend on the operating system. This is a required option." end newproperty(:options) do desc "Mount options for the mounts, as they would appear in the fstab." end newproperty(:pass) do desc "The pass in which the mount is checked." defaultto { 0 if @resource.managed? } end newproperty(:atboot) do desc "Whether to mount the mount at boot. Not all platforms support this." end newproperty(:dump) do desc "Whether to dump the mount. Not all platform support this. Valid values are `1` or `0`. or `2` on FreeBSD, Default is `0`." if Facter["operatingsystem"].value == "FreeBSD" newvalue(%r{(0|1|2)}) else newvalue(%r{(0|1)}) end newvalue(%r{(0|1)}) defaultto { 0 if @resource.managed? } end newproperty(:target) do desc "The file in which to store the mount table. Only used by those providers that write to disk." defaultto { if @resource.class.defaultprovider.ancestors.include?(Puppet::Provider::ParsedFile) @resource.class.defaultprovider.default_target else nil end } end newparam(:name) do desc "The mount path for the mount." isnamevar end newparam(:path) do desc "The deprecated name for the mount point. Please use `name` now." def value=(value) warning "'path' is deprecated for mounts. Please use 'name'." @resource[:name] = value super end end newparam(:remounts) do desc "Whether the mount can be remounted `mount -o remount`. If this is false, then the filesystem will be unmounted and remounted manually, which is prone to failure." newvalues(:true, :false) defaultto do case Facter.value(:operatingsystem) when "FreeBSD", "Darwin", "AIX" false else true end end end def refresh # Only remount if we're supposed to be mounted. - provider.remount if self.should(:fstype) != "swap" and provider.anything_mounted? + provider.remount if self.should(:fstype) != "swap" and provider.mounted? end def value(name) name = symbolize(name) ret = nil if property = @parameters[name] return property.value end end end end diff --git a/spec/fixtures/unit/provider/mount/mount-output.darwin.txt b/spec/fixtures/unit/provider/mount/mount-output.darwin.txt deleted file mode 100644 index fbb9d9832..000000000 --- a/spec/fixtures/unit/provider/mount/mount-output.darwin.txt +++ /dev/null @@ -1,5 +0,0 @@ -/dev/disk0s2 on / (hfs, local, journaled) -devfs on /dev (devfs, local, nobrowse) -map -hosts on /net (autofs, nosuid, automounted, nobrowse) -map auto_home on /home (autofs, automounted, nobrowse) -/dev/disk0s3 on /usr (hfs, local, journaled) diff --git a/spec/fixtures/unit/provider/mount/mount-output.hp-ux.txt b/spec/fixtures/unit/provider/mount/mount-output.hp-ux.txt deleted file mode 100644 index 477926138..000000000 --- a/spec/fixtures/unit/provider/mount/mount-output.hp-ux.txt +++ /dev/null @@ -1,16 +0,0 @@ -/ on rpool/ROOT/opensolaris read/write/setuid/devices/dev=2d90002 on Wed Dec 31 16:00:00 1969 -/devices on /devices read/write/setuid/devices/dev=4a00000 on Thu Feb 17 14:34:02 2011 -/dev on /dev read/write/setuid/devices/dev=4a40000 on Thu Feb 17 14:34:02 2011 -/system/contract on ctfs read/write/setuid/devices/dev=4ac0001 on Thu Feb 17 14:34:02 2011 -/proc on proc read/write/setuid/devices/dev=4b00000 on Thu Feb 17 14:34:02 2011 -/etc/mnttab on mnttab read/write/setuid/devices/dev=4b40001 on Thu Feb 17 14:34:02 2011 -/etc/svc/volatile on swap read/write/setuid/devices/xattr/dev=4b80001 on Thu Feb 17 14:34:02 2011 -/system/object on objfs read/write/setuid/devices/dev=4bc0001 on Thu Feb 17 14:34:02 2011 -/etc/dfs/sharetab on sharefs read/write/setuid/devices/dev=4c00001 on Thu Feb 17 14:34:02 2011 -/lib/libc.so.1 on /usr/lib/libc/libc_hwcap1.so.1 read/write/setuid/devices/dev=2d90002 on Thu Feb 17 14:34:14 2011 -/dev/fd on fd read/write/setuid/devices/dev=4d00001 on Thu Feb 17 14:34:18 2011 -/tmp on swap read/write/setuid/devices/xattr/dev=4b80002 on Thu Feb 17 14:34:19 2011 -/var/run on swap read/write/setuid/devices/xattr/dev=4b80003 on Thu Feb 17 14:34:19 2011 -/export on rpool/export read/write/setuid/devices/nonbmand/exec/xattr/atime/dev=2d90006 on Thu Feb 17 14:37:48 2011 -/export/home on rpool/export/home read/write/setuid/devices/nonbmand/exec/xattr/atime/dev=2d90007 on Thu Feb 17 14:37:48 2011 -/rpool on rpool read/write/setuid/devices/nonbmand/exec/xattr/atime/dev=2d90009 on Thu Feb 17 14:37:48 2011 diff --git a/spec/fixtures/unit/provider/mount/mount-output.other.txt b/spec/fixtures/unit/provider/mount/mount-output.other.txt deleted file mode 100644 index 0e4dff0c5..000000000 --- a/spec/fixtures/unit/provider/mount/mount-output.other.txt +++ /dev/null @@ -1,14 +0,0 @@ -/dev/sda1 on / type ext4 (rw,errors=remount-ro,commit=0) -proc on /proc type proc (rw,noexec,nosuid,nodev) -none on /sys type sysfs (rw,noexec,nosuid,nodev) -fusectl on /sys/fs/fuse/connections type fusectl (rw) -none on /sys/kernel/debug type debugfs (rw) -none on /sys/kernel/security type securityfs (rw) -none on /dev type devtmpfs (rw,mode=0755) -none on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620) -none on /dev/shm type tmpfs (rw,nosuid,nodev) -none on /var/run type tmpfs (rw,nosuid,mode=0755) -none on /var/lock type tmpfs (rw,noexec,nosuid,nodev) -none on /proc/fs/vmblock/mountPoint type vmblock (rw) -binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev) -/dev/sda2 on /usr type ext4 (rw,errors=remount-ro,commit=0) diff --git a/spec/fixtures/unit/provider/mount/mount-output.solaris.txt b/spec/fixtures/unit/provider/mount/mount-output.solaris.txt deleted file mode 100644 index 477926138..000000000 --- a/spec/fixtures/unit/provider/mount/mount-output.solaris.txt +++ /dev/null @@ -1,16 +0,0 @@ -/ on rpool/ROOT/opensolaris read/write/setuid/devices/dev=2d90002 on Wed Dec 31 16:00:00 1969 -/devices on /devices read/write/setuid/devices/dev=4a00000 on Thu Feb 17 14:34:02 2011 -/dev on /dev read/write/setuid/devices/dev=4a40000 on Thu Feb 17 14:34:02 2011 -/system/contract on ctfs read/write/setuid/devices/dev=4ac0001 on Thu Feb 17 14:34:02 2011 -/proc on proc read/write/setuid/devices/dev=4b00000 on Thu Feb 17 14:34:02 2011 -/etc/mnttab on mnttab read/write/setuid/devices/dev=4b40001 on Thu Feb 17 14:34:02 2011 -/etc/svc/volatile on swap read/write/setuid/devices/xattr/dev=4b80001 on Thu Feb 17 14:34:02 2011 -/system/object on objfs read/write/setuid/devices/dev=4bc0001 on Thu Feb 17 14:34:02 2011 -/etc/dfs/sharetab on sharefs read/write/setuid/devices/dev=4c00001 on Thu Feb 17 14:34:02 2011 -/lib/libc.so.1 on /usr/lib/libc/libc_hwcap1.so.1 read/write/setuid/devices/dev=2d90002 on Thu Feb 17 14:34:14 2011 -/dev/fd on fd read/write/setuid/devices/dev=4d00001 on Thu Feb 17 14:34:18 2011 -/tmp on swap read/write/setuid/devices/xattr/dev=4b80002 on Thu Feb 17 14:34:19 2011 -/var/run on swap read/write/setuid/devices/xattr/dev=4b80003 on Thu Feb 17 14:34:19 2011 -/export on rpool/export read/write/setuid/devices/nonbmand/exec/xattr/atime/dev=2d90006 on Thu Feb 17 14:37:48 2011 -/export/home on rpool/export/home read/write/setuid/devices/nonbmand/exec/xattr/atime/dev=2d90007 on Thu Feb 17 14:37:48 2011 -/rpool on rpool read/write/setuid/devices/nonbmand/exec/xattr/atime/dev=2d90009 on Thu Feb 17 14:37:48 2011 diff --git a/spec/unit/provider/mount/parsed_spec.rb b/spec/unit/provider/mount/parsed_spec.rb index 069d9495a..b4c2249fd 100755 --- a/spec/unit/provider/mount/parsed_spec.rb +++ b/spec/unit/provider/mount/parsed_spec.rb @@ -1,182 +1,182 @@ #!/usr/bin/env ruby # # Created by Luke Kanies on 2007-9-12. # Copyright (c) 2006. All rights reserved. require File.dirname(__FILE__) + '/../../../spec_helper' require 'puppettest/support/utils' require 'puppettest/fileparsing' module ParsedMountTesting include PuppetTest::Support::Utils include PuppetTest::FileParsing 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_class.default_target fakefile(File::join("data/types/mount", name)) end def mkmountargs mount = nil if defined?(@pcount) @pcount += 1 else @pcount = 1 end args = { :name => "/fspuppet#{@pcount}", :device => "/dev/dsk#{@pcount}", } @provider_class.fields(:parsed).each do |field| args[field] = "fake#{field}#{@pcount}" unless args.include? field end args end def mkmount hash = mkmountargs #hash[:provider] = @provider_class.name fakeresource = stub :type => :mount, :name => hash[:name] fakeresource.stubs(:[]).with(:name).returns(hash[:name]) fakeresource.stubs(:should).with(:target).returns(nil) mount = @provider_class.new(fakeresource) hash[:record_type] = :parsed hash[:ensure] = :present mount.property_hash = hash 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.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) end end provider_class = Puppet::Type.type(:mount).provider(:parsed) describe provider_class do before :each do @mount_class = Puppet::Type.type(:mount) @provider_class = @mount_class.provider(:parsed) end describe provider_class do include ParsedMountTesting it "should be able to parse all of the example mount tabs" do tab = fake_fstab @provider = @provider_class # LAK:FIXME Again, a relatively bad test, but I don't know how to rspec-ify this. # I suppose this is more of an integration test? I dunno. fakedataparse(tab) do # Now just make we've got some mounts we know will be there hashes = @provider_class.target_records(tab).find_all { |i| i.is_a? Hash } (hashes.length > 0).should be_true root = hashes.find { |i| i[:name] == "/" } proc { @provider_class.to_file(hashes) }.should_not raise_error end end # LAK:FIXME I can't mock Facter because this test happens at parse-time. it "should default to /etc/vfstab on Solaris and /etc/fstab everywhere else" do should = case Facter.value(:operatingsystem) when "Solaris"; "/etc/vfstab" else "/etc/fstab" end Puppet::Type.type(:mount).provider(:parsed).default_target.should == should end it "should not crash on incomplete lines in fstab" do parse = @provider_class.parse <<-FSTAB /dev/incomplete /dev/device name FSTAB lambda{ @provider_class.to_line(parse[0]) }.should_not raise_error end end describe provider_class, " when mounting an absent filesystem" do include ParsedMountTesting # #730 - Make sure 'flush' is called when a mount is moving from absent to mounted it "should flush the fstab to disk" do mount = mkmount # Mark the mount as absent mount.property_hash[:ensure] = :absent mount.stubs(:mountcmd) # just so we don't actually try to mount anything mount.expects(:flush) - mount.mount! + mount.mount end end describe provider_class, " when modifying the filesystem tab" do include ParsedMountTesting before do Puppet.settings.stubs(:use) # Never write to disk, only to RAM. #@provider_class.stubs(:filetype).returns(Puppet::Util::FileType.filetype(:ram)) @provider_class.stubs(:target_object).returns(Puppet::Util::FileType.filetype(:ram).new("eh")) @provider_class.clear @mount = mkmount @target = @provider_class.default_target end it "should write the mount to disk when :flush is called" do old_text = @provider_class.target_object(@provider_class.default_target).read @mount.flush text = @provider_class.target_object(@provider_class.default_target).read text.should == old_text + @mount.class.to_line(@mount.property_hash) + "\n" end end describe provider_class, " when parsing information about the root filesystem", :if => Facter["operatingsystem"].value != "Darwin" do include ParsedMountTesting before do @mount = @mount_class.new :name => "/" @provider = @mount.provider end it "should have a filesystem tab" do FileTest.should be_exist(@provider_class.default_target) end it "should find the root filesystem" do @provider_class.prefetch("/" => @mount) @mount.provider.property_hash[:ensure].should == :present end it "should determine that the root fs is mounted" do @provider_class.prefetch("/" => @mount) - @mount.provider.should be_anything_mounted + @mount.provider.should be_mounted end end end diff --git a/spec/unit/provider/mount_spec.rb b/spec/unit/provider/mount_spec.rb index 1f2501765..f567a4a40 100755 --- a/spec/unit/provider/mount_spec.rb +++ b/spec/unit/provider/mount_spec.rb @@ -1,202 +1,145 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' -require 'puppet_spec/files' require 'puppet/provider/mount' describe Puppet::Provider::Mount do - include PuppetSpec::Files - before :each do + @mounter = Object.new + @mounter.extend(Puppet::Provider::Mount) + @name = "/" - @resource = Puppet::Type.type(:mount).new( - :name => '/', - :device => '/dev/sda1', - :target => tmpfile("mount_provider") - ) + @resource = stub 'resource' + @resource.stubs(:[]).with(:name).returns(@name) - @mounter = Puppet::Type.type(:mount).defaultprovider().new(@resource) + @mounter.stubs(:resource).returns(@resource) end - describe "when calling mount!" do + describe Puppet::Provider::Mount, " when mounting" do + it "should use the 'mountcmd' method to mount" do @mounter.stubs(:options).returns(nil) @mounter.expects(:mountcmd) - @mounter.mount! + @mounter.mount end it "should flush before mounting if a flush method exists" do @mounter.meta_def(:flush) { } @mounter.expects(:flush) @mounter.stubs(:mountcmd) @mounter.stubs(:options).returns(nil) - @mounter.mount! + @mounter.mount end it "should add the options following '-o' if they exist and are not set to :absent" do @mounter.stubs(:options).returns("ro") @mounter.expects(:mountcmd).with { |*ary| ary[0] == "-o" and ary[1] == "ro" } - @mounter.mount! + @mounter.mount end it "should specify the filesystem name to the mount command" do @mounter.stubs(:options).returns(nil) @mounter.expects(:mountcmd).with { |*ary| ary[-1] == @name } - @mounter.mount! + @mounter.mount end end - describe "when remounting" do + describe Puppet::Provider::Mount, " when remounting" do + it "should use '-o remount' if the resource specifies it supports remounting" do @mounter.stubs(:info) - @resource[:remounts] = true + @resource.stubs(:[]).with(:remounts).returns(:true) @mounter.expects(:mountcmd).with("-o", "remount", @name) @mounter.remount end it "should unmount and mount if the resource does not specify it supports remounting" do @mounter.stubs(:info) - @resource[:remounts] = false + @resource.stubs(:[]).with(:remounts).returns(false) @mounter.expects(:unmount) @mounter.expects(:mount) @mounter.remount end it "should log that it is remounting" do - @resource[:remounts] = true + @resource.stubs(:[]).with(:remounts).returns(:true) @mounter.stubs(:mountcmd) @mounter.expects(:info).with("Remounting") @mounter.remount end end - describe "when unmounting" do + describe Puppet::Provider::Mount, " when unmounting" do + it "should call the :umount command with the resource name" do @mounter.expects(:umount).with(@name) @mounter.unmount end end - %w{Darwin Solaris HP-UX AIX Other}.each do |platform| - describe "on #{platform}" do - before :each do - case platform - when 'Darwin' - mount_fixture = 'mount-output.darwin.txt' - @mount_device = '/dev/disk0s3' - @mount_point = '/usr' - when 'Solaris' - mount_fixture = 'mount-output.solaris.txt' - @mount_device = 'swap' - @mount_point = '/tmp' - when 'HP-UX' - mount_fixture = 'mount-output.hp-ux.txt' - @mount_device = 'swap' - @mount_point = '/tmp' - when 'AIX' - mount_fixture = 'mount-output.aix.txt' - @mount_device = '/dev/hd2' - @mount_point = '/usr' - when 'Other' - mount_fixture = 'mount-output.other.txt' - @mount_device = '/dev/sda2' - @mount_point = '/usr' - end - @mount_data = File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'unit', 'provider', 'mount', mount_fixture)) - Facter.stubs(:value).with("operatingsystem").returns(platform) - end - - describe "when the correct thing is mounted" do - before :each do - @mounter.expects(:mountcmd).returns(@mount_data) - @resource.stubs(:[]).with(:name).returns(@mount_point) - @resource.stubs(:[]).with(:device).returns(@mount_device) - end - - it "should say anything_mounted?" do - @mounter.should be_anything_mounted - end - - it "should say correctly_mounted?" do - @mounter.should be_correctly_mounted - end - end - - describe "when the wrong thing is mounted" do - before :each do - @mounter.expects(:mountcmd).returns(@mount_data) - @resource.stubs(:[]).with(:name).returns(@mount_point) - @resource.stubs(:[]).with(:device).returns('/dev/bogus/thing') - end - - it "should say anything_mounted?" do - @mounter.should be_anything_mounted - end - - it "should not say correctly_mounted?" do - @mounter.should_not be_correctly_mounted - end - end - - describe "when nothing is mounted" do - before :each do - @mounter.expects(:mountcmd).returns(@mount_data) - @resource.stubs(:[]).with(:name).returns('/bogus/location') - @resource.stubs(:[]).with(:device).returns(@mount_device) - end - - it "should not say anything_mounted?" do - @mounter.should_not be_anything_mounted - end - - it "should not say correctly_mounted?" do - @mounter.should_not be_correctly_mounted - end - end + describe Puppet::Provider::Mount, " when determining if it is mounted" do + + it "should parse the results of running the mount command with no arguments" do + Facter.stubs(:value).returns("whatever") + @mounter.expects(:mountcmd).returns("") + + @mounter.mounted? end - end - describe "when mounting a device" do - it "should not mount! or unmount anything when the correct device is mounted" do - @mounter.stubs(:correctly_mounted?).returns(true) + it "should match ' on /private/var/automount' if the operating system is Darwin" do + Facter.stubs(:value).with("operatingsystem").returns("Darwin") + @mounter.expects(:mountcmd).returns("/dev/whatever on /private/var/automount/\ndevfs on /dev") - @mounter.expects(:anything_mounted?).never - @mounter.expects(:create).once - @mounter.expects(:mount!).never - @mounter.expects(:unmount).never - FileUtils.expects(:mkdir_p).never + @mounter.should be_mounted + end - @mounter.mount + it "should match ' on ' if the operating system is Darwin" do + Facter.stubs(:value).with("operatingsystem").returns("Darwin") + @mounter.expects(:mountcmd).returns("/dev/disk03 on / (local, journaled)\ndevfs on /dev") + + @mounter.should be_mounted end - it "should mount the device when nothing is mounted at the desired point" do - @mounter.stubs(:correctly_mounted?).returns(false) - @mounter.stubs(:anything_mounted?).returns(false) + it "should match '^ on' if the operating system is Solaris" do + Facter.stubs(:value).with("operatingsystem").returns("Solaris") + @mounter.expects(:mountcmd).returns("/ on /dev/dsk/whatever\n/var on /dev/dsk/other") - @mounter.expects(:create).once - @mounter.expects(:mount!).once - @mounter.expects(:unmount).never - FileUtils.expects(:mkdir_p).never + @mounter.should be_mounted + end - @mounter.mount + it "should match '^ on' if the operating system is HP-UX" do + Facter.stubs(:value).with("operatingsystem").returns("HP-UX") + @mounter.expects(:mountcmd).returns("/ on /dev/dsk/whatever\n/var on /dev/dsk/other") + + @mounter.should be_mounted end - it "should unmount the incorrect device and mount the correct device" do - @mounter.stubs(:correctly_mounted?).returns(false) - @mounter.stubs(:anything_mounted?).returns(true) + it "should match mounted devices if the operating system is AIX" do + Facter.stubs(:value).with("operatingsystem").returns("AIX") + mount_data = File.read(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'unit', 'provider', 'mount', 'mount-output.aix.txt')) + @mounter.expects(:mountcmd).returns(mount_data) - @mounter.expects(:create).once - @mounter.expects(:mount!).once - @mounter.expects(:unmount).once - FileUtils.expects(:mkdir_p).with(@name).returns(true) + @mounter.should be_mounted + end - @mounter.mount + it "should match ' on ' if the operating system is not Darwin, Solaris, or HP-UX" do + Facter.stubs(:value).with("operatingsystem").returns("Debian") + @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on / and stuff\n/dev/other/disk on /var and stuff") + + @mounter.should be_mounted + end + + it "should not be considered mounted if it did not match the mount output" do + Facter.stubs(:value).with("operatingsystem").returns("Debian") + @mounter.expects(:mountcmd).returns("/dev/dsk/whatever on /something/else and stuff\n/dev/other/disk on /var and stuff") + + @mounter.should_not be_mounted end end end diff --git a/spec/unit/type/mount_spec.rb b/spec/unit/type/mount_spec.rb index c6d2b5ba0..0d74042e3 100755 --- a/spec/unit/type/mount_spec.rb +++ b/spec/unit/type/mount_spec.rb @@ -1,239 +1,261 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' describe Puppet::Type.type(:mount) do it "should have a :refreshable feature that requires the :remount method" do Puppet::Type.type(:mount).provider_feature(:refreshable).methods.should == [:remount] end it "should have no default value for :ensure" do mount = Puppet::Type.type(:mount).new(:name => "yay") mount.should(:ensure).should be_nil end end describe Puppet::Type.type(:mount), "when validating attributes" do [:name, :remounts].each do |param| it "should have a #{param} parameter" do Puppet::Type.type(:mount).attrtype(param).should == :param end end [:ensure, :device, :blockdevice, :fstype, :options, :pass, :dump, :atboot, :target].each do |param| it "should have a #{param} property" do Puppet::Type.type(:mount).attrtype(param).should == :property end end end describe Puppet::Type.type(:mount)::Ensure, "when validating values" do before do @provider = stub 'provider', :class => Puppet::Type.type(:mount).defaultprovider, :clear => nil Puppet::Type.type(:mount).defaultprovider.expects(:new).returns(@provider) end it "should alias :present to :defined as a value to :ensure" do mount = Puppet::Type.type(:mount).new(:name => "yay", :ensure => :present) mount.should(:ensure).should == :defined end it "should support :unmounted as a value to :ensure" do mount = Puppet::Type.type(:mount).new(:name => "yay", :ensure => :unmounted) mount.should(:ensure).should == :unmounted end it "should support :absent as a value to :ensure" do Puppet::Type.type(:mount).new(:name => "yay", :ensure => :absent) end it "should support :mounted as a value to :ensure" do Puppet::Type.type(:mount).new(:name => "yay", :ensure => :mounted) end end describe Puppet::Type.type(:mount)::Ensure do before :each do @provider = stub 'provider', :class => Puppet::Type.type(:mount).defaultprovider, :clear => nil, :satisfies? => true, :name => :mock Puppet::Type.type(:mount).defaultprovider.stubs(:new).returns(@provider) @mount = Puppet::Type.type(:mount).new(:name => "yay", :check => :ensure) @ensure = @mount.property(:ensure) end def mount_stub(params) Puppet::Type.type(:mount).validproperties.each do |prop| unless params[prop] params[prop] = :absent @mount[prop] = :absent end end params.each do |param, value| @provider.stubs(param).returns(value) end end - describe "when retrieving its current state" do + describe Puppet::Type.type(:mount)::Ensure, "when retrieving its current state" do + it "should return the provider's value if it is :absent" do @provider.expects(:ensure).returns(:absent) @ensure.retrieve.should == :absent end it "should return :mounted if the provider indicates it is mounted and the value is not :absent" do @provider.expects(:ensure).returns(:present) - @provider.expects(:correctly_mounted?).returns(true) + @provider.expects(:mounted?).returns(true) @ensure.retrieve.should == :mounted end it "should return :unmounted if the provider indicates it is not mounted and the value is not :absent" do @provider.expects(:ensure).returns(:present) - @provider.expects(:correctly_mounted?).returns(false) + @provider.expects(:mounted?).returns(false) @ensure.retrieve.should == :unmounted end end - describe "when changing the host" do + describe Puppet::Type.type(:mount)::Ensure, "when changing the host" do + it "should destroy itself if it should be absent" do - @provider.stubs(:anything_mounted?).returns(false) + @provider.stubs(:mounted?).returns(false) @provider.expects(:destroy) @ensure.should = :absent @ensure.sync end it "should unmount itself before destroying if it is mounted and should be absent" do - @provider.expects(:anything_mounted?).returns(true) + @provider.expects(:mounted?).returns(true) @provider.expects(:unmount) @provider.expects(:destroy) @ensure.should = :absent @ensure.sync end it "should create itself if it is absent and should be defined" do @provider.stubs(:ensure).returns(:absent) - @provider.stubs(:anything_mounted?).returns(true) + @provider.stubs(:mounted?).returns(true) - @provider.stubs(:anything_mounted?).returns(false) + @provider.stubs(:mounted?).returns(false) @provider.expects(:create) @ensure.should = :defined @ensure.sync end it "should not unmount itself if it is mounted and should be defined" do @provider.stubs(:ensure).returns(:mounted) - @provider.stubs(:anything_mounted?).returns(true) + @provider.stubs(:mounted?).returns(true) @provider.stubs(:create) @provider.expects(:mount).never @provider.expects(:unmount).never @ensure.should = :defined @ensure.sync end it "should not mount itself if it is unmounted and should be defined" do @provider.stubs(:ensure).returns(:unmounted) - @provider.stubs(:anything_mounted?).returns(false) + @provider.stubs(:mounted?).returns(false) @ensure.stubs(:syncothers) @provider.stubs(:create) @provider.expects(:mount).never @provider.expects(:unmount).never @ensure.should = :present @ensure.sync end it "should unmount itself if it is mounted and should be unmounted" do @provider.stubs(:ensure).returns(:present) - @provider.stubs(:anything_mounted?).returns(true) + @provider.stubs(:mounted?).returns(true) @ensure.stubs(:syncothers) @provider.expects(:unmount) @ensure.should = :unmounted @ensure.sync end - it "should ask the provider to mount itself" do + it "should create and mount itself if it does not exist and should be mounted" do + @provider.stubs(:ensure).returns(:absent) + @provider.stubs(:mounted?).returns(false) + @provider.expects(:create) + @ensure.stubs(:syncothers) + @provider.expects(:mount) + @ensure.should = :mounted + @ensure.sync + end + + it "should mount itself if it is present and should be mounted" do @provider.stubs(:ensure).returns(:present) + @provider.stubs(:mounted?).returns(false) @ensure.stubs(:syncothers) @provider.expects(:mount) @ensure.should = :mounted @ensure.sync end + it "should create but not mount itself if it is absent and mounted and should be mounted" do + @provider.stubs(:ensure).returns(:absent) + @provider.stubs(:mounted?).returns(true) + @ensure.stubs(:syncothers) + @provider.expects(:create) + @ensure.should = :mounted + @ensure.sync + end + it "should be insync if it is mounted and should be defined" do @ensure.should = :defined @ensure.safe_insync?(:mounted).should == true end it "should be insync if it is unmounted and should be defined" do @ensure.should = :defined @ensure.safe_insync?(:unmounted).should == true end it "should be insync if it is mounted and should be present" do @ensure.should = :present @ensure.safe_insync?(:mounted).should == true end it "should be insync if it is unmounted and should be present" do @ensure.should = :present @ensure.safe_insync?(:unmounted).should == true end end - describe "when responding to events" do + describe Puppet::Type.type(:mount), "when responding to events" do + it "should remount if it is currently mounted" do - @provider.expects(:anything_mounted?).returns(true) + @provider.expects(:mounted?).returns(true) @provider.expects(:remount) @mount.refresh end it "should not remount if it is not currently mounted" do - @provider.expects(:anything_mounted?).returns(false) + @provider.expects(:mounted?).returns(false) @provider.expects(:remount).never @mount.refresh end it "should not remount swap filesystems" do @mount[:fstype] = "swap" @provider.expects(:remount).never @mount.refresh end end end describe Puppet::Type.type(:mount), "when modifying an existing mount entry" do before do @provider = stub 'provider', :class => Puppet::Type.type(:mount).defaultprovider, :clear => nil, :satisfies? => true, :name => :mock, :remount => nil Puppet::Type.type(:mount).defaultprovider.stubs(:new).returns(@provider) @mount = Puppet::Type.type(:mount).new(:name => "yay", :ensure => :mounted) {:device => "/foo/bar", :blockdevice => "/other/bar", :target => "/what/ever", :fstype => 'eh', :options => "", :pass => 0, :dump => 0, :atboot => 0, :ensure => :mounted}.each do |param, value| @mount.provider.stubs(param).returns value @mount[param] = value end - @mount.provider.stubs(:anything_mounted?).returns true - @mount.provider.stubs(:correctly_mounted?).returns true + @mount.provider.stubs(:mounted?).returns true # stub this to not try to create state.yaml Puppet::Util::Storage.stubs(:store) @catalog = Puppet::Resource::Catalog.new @catalog.add_resource @mount end it "should use the provider to change the dump value" do @mount.provider.expects(:dump).returns 0 @mount.provider.expects(:dump=).with(1) @mount[:dump] = 1 @catalog.apply end end