lib/puppet/server/fileserver.rb in puppet-0.13.6 vs lib/puppet/server/fileserver.rb in puppet-0.16.0
- old
+ new
@@ -1,12 +1,12 @@
require 'puppet'
require 'webrick/httpstatus'
require 'cgi'
module Puppet
+class FileServerError < Puppet::Error; end
class Server
- class FileServerError < Puppet::Error; end
class FileServer < Handler
attr_accessor :local
Puppet.setdefaults("fileserver",
:fileserverconfig => ["$confdir/fileserver.conf",
@@ -14,76 +14,64 @@
#CHECKPARAMS = %w{checksum type mode owner group}
CHECKPARAMS = [:mode, :type, :owner, :group, :checksum]
@interface = XMLRPC::Service::Interface.new("fileserver") { |iface|
- iface.add_method("string describe(string)")
- iface.add_method("string list(string, boolean, array)")
- iface.add_method("string retrieve(string)")
+ iface.add_method("string describe(string, string)")
+ iface.add_method("string list(string, string, boolean, array)")
+ iface.add_method("string retrieve(string, string)")
}
def authcheck(file, mount, client, clientip)
unless mount.allowed?(client, clientip)
- Puppet.warning "%s cannot access %s in %s" %
- [client, mount, file]
+ mount.warning "%s cannot access %s" %
+ [client, file]
raise Puppet::Server::AuthorizationError, "Cannot access %s" % mount
end
end
- # Run 'retrieve' on a file. This gets the actual parameters, so
- # we can pass them to the client.
- def check(dir)
- unless FileTest.exists?(dir)
- Puppet.notice "File source %s does not exist" % dir
- return nil
- end
-
- obj = nil
- unless obj = Puppet.type(:file)[dir]
- obj = Puppet.type(:file).create(
- :name => dir,
- :check => CHECKPARAMS
- )
- end
- # we should really have a timeout here -- we don't
- # want to actually check on every connection, maybe no more
- # than every 60 seconds or something
- #@files[mount].evaluate
- obj.evaluate
-
- return obj
- end
-
# Describe a given file. This returns all of the manageable aspects
# of that file.
- def describe(file, client = nil, clientip = nil)
+ def describe(file, links = :ignore, client = nil, clientip = nil)
readconfig
+
+ links = links.intern if links.is_a? String
+
+ if links == :manage
+ raise Puppet::FileServerError, "Cannot currently copy links"
+ end
+
mount, path = splitpath(file)
authcheck(file, mount, client, clientip)
if client
- Puppet.debug "Describing %s for %s" % [file, client]
+ mount.debug "Describing %s for %s" % [file, client]
end
sdir = nil
unless sdir = subdir(mount, path)
mount.notice "Could not find subdirectory %s" %
"//%s/%s" % [mount, path]
return ""
end
obj = nil
- unless obj = self.check(sdir)
+ unless obj = mount.check(sdir, links)
return ""
end
+ #if links == :ignore and obj[:type] == "link"
+ # mount.info "Ignoring link %s" % obj.name
+ # return ""
+ #end
+
desc = []
CHECKPARAMS.each { |check|
if state = obj.state(check)
unless state.is
- mount.notice "Manually retrieving info for %s" % check
+ mount.debug "Manually retrieving info for %s" % check
state.retrieve
end
desc << state.is
else
if check == "checksum" and obj.state(:type).is == "file"
@@ -146,18 +134,18 @@
readconfig
end
end
# List a specific directory's contents.
- def list(dir, recurse = false, ignore = false, client = nil, clientip = nil)
+ def list(dir, links = :ignore, recurse = false, ignore = false, client = nil, clientip = nil)
readconfig
mount, path = splitpath(dir)
authcheck(dir, mount, client, clientip)
if client
- Puppet.debug "Listing %s for %s" % [dir, client]
+ mount.debug "Listing %s for %s" % [dir, client]
end
subdir = nil
unless subdir = subdir(mount, path)
mount.notice "Could not find subdirectory %s" %
@@ -197,11 +185,11 @@
end
if FileTest.directory?(path)
if FileTest.readable?(path)
@mounts[name] = Mount.new(name, path)
- @mounts[name].info "Mounted"
+ @mounts[name].info "Mounted %s" % path
else
raise FileServerError, "%s is not readable" % path
end
else
raise FileServerError, "%s is not a directory" % path
@@ -309,18 +297,19 @@
@configstatted = Time.now
end
# Retrieve a file from the local disk and pass it to the remote
# client.
- def retrieve(file, client = nil, clientip = nil)
+ def retrieve(file, links = :ignore, client = nil, clientip = nil)
readconfig
+ links = links.intern if links.is_a? String
mount, path = splitpath(file)
authcheck(file, mount, client, clientip)
if client
- Puppet.info "Sending %s to %s" % [file, client]
+ mount.info "Sending %s to %s" % [file, client]
end
fpath = nil
if path
fpath = File.join(mount.path, path)
@@ -330,12 +319,23 @@
unless FileTest.exists?(fpath)
return ""
end
- str = File.read(fpath)
+ links = links.intern if links.is_a? String
+ if links == :ignore and FileTest.symlink?(fpath)
+ return ""
+ end
+
+ str = nil
+ if links == :manage
+ raise Puppet::Error, "Cannot copy links yet."
+ else
+ str = File.read(fpath)
+ end
+
if @local
return str
else
return CGI.escape(str)
end
@@ -351,11 +351,12 @@
name.sub(/\/#{mount.name}/, mount.path).gsub(%r{/+}, '/').sub(
%r{/$}, ''
)
end
- # Recursively list the directory.
+ # Recursively list the directory. FIXME This should be using
+ # puppet objects, not directly listing.
def reclist(mount, root, path, recurse, ignore)
# Take out the root of the path.
name = path.sub(root, '')
if name == ""
name = "/"
@@ -439,18 +440,47 @@
end
dirname
end
+ def to_s
+ "fileserver"
+ end
+
# A simple class for wrapping mount points. Instances of this class
# don't know about the enclosing object; they're mainly just used for
# authorization.
class Mount < AuthStore
attr_reader :path, :name
Puppet::Util.logmethods(self, true)
+ # Run 'retrieve' on a file. This gets the actual parameters, so
+ # we can pass them to the client.
+ def check(dir, links)
+ unless FileTest.exists?(dir)
+ self.notice "File source %s does not exist" % dir
+ return nil
+ end
+
+ obj = fileobj(dir, links)
+
+ # FIXME we should really have a timeout here -- we don't
+ # want to actually check on every connection, maybe no more
+ # than every 60 seconds or something. It'd be nice if we
+ # could use the builtin scheduling to do this.
+
+ # Retrieval is enough here, because we don't want to cache
+ # any information in the state file, and we don't want to generate
+ # any state changes or anything. We don't even need to sync
+ # the checksum, because we're always going to hit the disk
+ # directly.
+ obj.retrieve
+
+ return obj
+ end
+
# Create out orbject. It must have a name.
def initialize(name, path = nil)
unless name =~ %r{^\w+$}
raise FileServerError, "Invalid name format '%s'" % name
end
@@ -460,29 +490,68 @@
self.path = path
else
@path = nil
end
+ @comp = Puppet.type(:component).create(
+ :name => "mount[#{name}]"
+ )
+ #@comp.type = "mount"
+ #@comp.name = name
+
super()
end
+ def fileobj(path, links)
+ obj = nil
+ if obj = Puppet.type(:file)[path]
+ # This can only happen in local fileserving, but it's an
+ # important one. It'd be nice if we didn't just set
+ # the check params every time, but I'm not sure it's worth
+ # the effort.
+ obj[:check] = CHECKPARAMS
+ else
+ obj = Puppet.type(:file).create(
+ :name => path,
+ :check => CHECKPARAMS
+ )
+
+ @comp.push(obj)
+ end
+
+ if links == :manage
+ links = :follow
+ end
+
+ # This, ah, might be completely redundant
+ unless obj[:links] == links
+ obj[:links] = links
+ end
+
+ return obj
+ end
+
# Set the path.
def path=(path)
unless FileTest.exists?(path)
raise FileServerError, "%s does not exist" % path
end
@path = path
end
def to_s
- if @path
- @name + ":" + @path
- else
- @name
- end
+ #if @path
+ # "mount[#{@name}]" + ":" + @path
+ #else
+ # "mount[#{@name}]"
+ #end
+ "mount[#{@name}]"
end
+ def type?(file)
+ end
+
# Verify our configuration is valid. This should really check to
# make sure at least someone will be allowed, but, eh.
def valid?
unless @path
raise FileServerError, "No path specified"
@@ -491,6 +560,6 @@
end
end
end
end
-# $Id: fileserver.rb 962 2006-03-01 22:28:27Z luke $
+# $Id: fileserver.rb 989 2006-03-06 21:19:34Z luke $