from mount1 import * from nfs2 import * from nfscommon import * from sunrpc import AuthFlavor from string import split from rpcserver import ProcedureServer auth_flavors = ( AuthFlavor.AUTH_NONE, AuthFlavor.AUTH_SYS, AuthFlavor.AUTH_SHORT, ) class MountError(Exception): def __init__(self, status): self._status = status class MountServer(ProcedureServer): def __init__(self, fs, exports): self._fs = fs self._exports = exports self._mounts = [] def null(self, authinfo): pass def mnt(self, authinfo, dirpath): try: best = '' best_hosts = None for p, hosts in self._exports.items(): lp = len(p) if dirpath == p: best = p best_hosts = hosts break elif dirpath[:lp] == p and (dirpath[lp] == '/' or p[-1] == '/'): if lp > len(best): best = p best_hosts = hosts if not best: raise MountError(MountStat.MNTERR_ACCESS) hostname = authinfo.hostname if not hostname in best_hosts: raise MountError(MountStat.MNTERR_ACCESS) fs = self._fs ob = fs.getRoot() dp = split(dirpath, '/') for n in dp: if not n: continue if not fs.isDirectory(ob): raise MountError(MountStat.MNTERR_NOTDIR) ob = fs.getFileFrom(ob, n) if ob is None: raise MountError(MountStat.MNTERR_NOENT) handle = fs.getHandleOf(ob) self._mounts.append((hostname, dirpath)) info = mnt_resok(fhandle=NFSFH(handle), auth_flavors=auth_flavors) return mnt_res(fhs_status=MountStat.MNT_OK, mountinfo=info) except MountError, exc: return mnt_res(fhs_status=exc._status) except NFSError, exc: # This is a little sneaky: MountStat and NFSStat are # very similar, so we can generally just return an # NFSStat as if it were a MountStat. return mnt_res(fhs_status=exc._status) def dump(self, authinfo): mountlist = [] for hostname, dirpath in self._mounts: mountlist.append(MountBody(ml_hostname=hostname, ml_directory=dirpath)) return dump_res(mountlist=mountlist) def umnt(self, authinfo, dirpath): hostname = authinfo.hostname idx = 0 mounts = self._mounts for idx in range(len(mounts)): h, d = mounts[idx] if h == hostname and d == dirpath: del mounts[idx] else: idx = idx + 1 def umntall(self, authinfo): hostname = authinfo.hostname idx = 0 mounts = self._mounts for idx in range(len(mounts)): h, d = mounts[idx] if h == hostname: del mounts[idx] else: idx = idx + 1 def exports(self, authinfo): exps = [] for dirpath, hostnames in self._exports.items(): groups = [] for host in hostnames: groups.append(ExportGroupNode(name=host)) exps.append(ExportNode(dir=dirpath, groups=groups)) return exports_res(exports=exps) class NFSServer(ProcedureServer): def __init__(self, fs): self._fs = fs def _callProcedure(self, procName, args, resClass, authinfo): m = getattr(self, procName) try: if args: res = apply(m, (), args.__dict__) else: res = apply(m) except NFSError, exc: return NFSStatResult(exc._status) #print procName, '\t', args, '\t', res if not resClass: if res: raise TypeError('Expected no result, got %s' % repr(res)) elif res.__class__ != resClass: raise TypeError('Expected a result of type %s, ' 'got %s' % (resClass, repr(res))) return res def _getFileByHandle(self, nfsfh): file = self._fs.getFileByHandle(nfsfh.data) if file is None: raise NFSError(NFSStat.NFSERR_STALE) else: return file def null(self): pass def getattr(self, handle): file = self._getFileByHandle(handle) attrs = self._fs.getAttributesOf(file, FAttr) return getattr_res(status=NFSStat.NFS_OK, attributes=attrs) def setattr(self, handle, attributes): file = self._getFileByHandle(handle) self._fs.setAttributesOf(file, attributes) attrs = self._fs.getAttributesOf(file, FAttr) return setattr_res(status=NFSStat.NFS_OK, attributes=attrs) root = null def lookup(self, what): fs = self._fs dir = self._getFileByHandle(what.dir) file = fs.getFileFrom(dir, what.name) if file is None: raise NFSError(NFSStat.NFSERR_NOENT) handle = NFSFH(fs.getHandleOf(file)) attrs = fs.getAttributesOf(file, FAttr) return lookup_res(status=NFSStat.NFS_OK, handle=handle, attributes=attrs) def readlink(self, handle): raise NFSError(NFSStat.NFSERR_IO) # return readlink_res(status=NFSStat.NFS_OK, data='/') def read(self, handle, offset, count, totalcount): fs = self._fs file = self._getFileByHandle(handle) data = fs.readFrom(file, offset, count) attrs = fs.getAttributesOf(file, FAttr) return read_res(status=NFSStat.NFS_OK, attributes=attrs, data=data) writecache = null def write(self, handle, beginoffset, offset, totalcount, data): fs = self._fs file = self._getFileByHandle(handle) fs.writeTo(file, offset, data) attrs = fs.getAttributesOf(file, FAttr) return write_res(status=NFSStat.NFS_OK, attributes=attrs) def create(self, where, attributes): fs = self._fs dir = self._getFileByHandle(where.dir) file = fs.createIn(dir, where.name, attributes) handle = NFSFH(fs.getHandleOf(file)) attrs = fs.getAttributesOf(file, FAttr) return create_res(status=NFSStat.NFS_OK, handle=handle, attributes=attrs) def remove(self, object): fs = self._fs dir = self._getFileByHandle(object.dir) fs.removeFrom(dir, object.name, rmdir=0) return remove_res(status=NFSStat.NFS_OK) def rename(self, rename_from, rename_to): fs = self._fs dir1 = self._getFileByHandle(rename_from.dir) dir2 = self._getFileByHandle(rename_to.dir) fs.rename(dir1, rename_from.name, dir2, rename_to.name) return rename_res(status=NFSStat.NFS_OK) def hardlink(self, handle, where): fs = self._fs file = self._getFileByHandle(handle) dir = self._getFileByHandle(where.dir) fs.createLink(dir, where.name, hard_dest=file) return hardlink_res(status=NFSStat.NFS_OK) def symlink(self, where, path, attributes): fs = self._fs dir = self._getFileByHandle(where.dir) fs.createLink(dir, where.name, sym_path=path, attrs=attributes) return symlink_res(status=NFSStat.NFS_OK) def mkdir(self, where, attributes): fs = self._fs dir = self._getFileByHandle(where.dir) file = fs.createDirectoryIn(dir, where.name, attributes) handle = NFSFH(fs.getHandleOf(file)) attrs = fs.getAttributesOf(file, FAttr) return mkdir_res(status=NFSStat.NFS_OK, handle=handle, attributes=attrs) def rmdir(self, object): fs = self._fs dir = self._getFileByHandle(object.dir) fs.removeFrom(dir, object.name, rmdir=1) return rmdir_res(status=NFSStat.NFS_OK) def readdir(self, handle, cookie, count): fs = self._fs dir = self._getFileByHandle(handle) entries, eof = fs.getDirectoryEntriesFrom(dir, cookie, count, Entry) return readdir_res(status=NFSStat.NFS_OK, reply=DirList(entries=entries, eof=eof)) def statfs(self, root_handle): file = self._getFileByHandle(root_handle) info = self._fs.getFilesystemStatus(file, statfs_resok) return statfs_res(status=NFSStat.NFS_OK, info=info)