Skip to content

Commit

Permalink
Merge 291f770 into c1de61a
Browse files Browse the repository at this point in the history
  • Loading branch information
siddharthv committed Feb 25, 2015
2 parents c1de61a + 291f770 commit eaa9735
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 33 deletions.
2 changes: 1 addition & 1 deletion drivers/NFSSR.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
['serverpath', 'path on remote server (required)'],
nfs.NFS_VERSION]


DRIVER_INFO = {
'name': 'NFS VHD',
'description': 'SR plugin which stores disks as VHD files on a remote NFS filesystem',
Expand Down
80 changes: 48 additions & 32 deletions drivers/nfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
#
# Copyright (C) Citrix Systems Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; version 2.1 only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
Expand All @@ -17,56 +17,67 @@
#
# nfs.py: NFS related utility functions

import util, errno, os, xml.dom.minidom
import util
import errno
import os
import xml.dom.minidom

# The algorithm for tcp and udp (at least in the linux kernel) for
# The algorithm for tcp and udp (at least in the linux kernel) for
# NFS timeout on softmounts is as follows:
#
# UDP:
# As long as the request wasn't started more than timeo * (2 ^ retrans)
# As long as the request wasn't started more than timeo * (2 ^ retrans)
# in the past, keep doubling the timeout.
#
# TCP:
# As long as the request wasn't started more than timeo * (1 + retrans)
# As long as the request wasn't started more than timeo * (1 + retrans)
# in the past, keep increaing the timeout by timeo.
#
# The time when the retrans may retry has been made will be:
# For udp: timeo * (2 ^ retrans * 2 - 1)
# For tcp: timeo * n! where n is the smallest n for which n! > 1 + retrans
#
# thus for retrans=1, timeo can be the same for both tcp and udp,
# thus for retrans=1, timeo can be the same for both tcp and udp,
# because the first doubling (timeo*2) is the same as the first increment
# (timeo+timeo).

SOFTMOUNT_TIMEOUT = 60 # seconds
SOFTMOUNT_RETRANS = 0x7fffffff
SOFTMOUNT_TIMEOUT = 60 # seconds
SOFTMOUNT_RETRANS = 0x7fffffff
RPCINFO_BIN = "/usr/sbin/rpcinfo"
SHOWMOUNT_BIN = "/usr/sbin/showmount"

DEFAULT_NFSVERSION = '3'

NFS_VERSION = [
'nfsversion', 'for type=nfs, NFS protocol version - 3, 4 (optional)']
'nfsversion', 'for type=nfs, NFS protocol version - 3, 4']


class NfsException(Exception):

def __init__(self, errstr):
self.errstr = errstr


def check_server_tcp(server, nfsversion=DEFAULT_NFSVERSION):
"""Make sure that NFS over TCP/IP V3 is supported on the server.
Returns True if everything is OK, False otherwise."""
"""Make sure that NFS over TCP/IP V3 is supported on the server.
Returns True if everything is OK
False otherwise.
"""
try:
util.ioretry(lambda: util.pread([RPCINFO_BIN,"-t",
util.ioretry(lambda: util.pread([RPCINFO_BIN, "-t",
"%s" % server, "nfs", nfsversion]),
errlist=[errno.EPERM], maxretry=2, nofail=True)
except util.CommandException, inst:
raise NfsException("rpcinfo failed or timed out: return code %d" %
raise NfsException("rpcinfo failed or timed out: return code %d" %
inst.code)


def validate_nfsversion(nfsversion):
"""Check the validity of 'nfsversion'.
Raise an exception for any invalid version.
"""
if not nfsversion:
nfsversion = DEFAULT_NFSVERSION
else:
Expand All @@ -78,13 +89,15 @@ def validate_nfsversion(nfsversion):
def soft_mount(mountpoint, remoteserver, remotepath, transport, timeout=0,
nfsversion=DEFAULT_NFSVERSION):
"""Mount the remote NFS export at 'mountpoint'.
The 'timeout' param here is in seconds"""
The 'timeout' param here is in seconds
"""
try:
if not util.ioretry(lambda: util.isdir(mountpoint)):
util.ioretry(lambda: util.makedirs(mountpoint))
except util.CommandException, inst:
raise NfsException("Failed to make directory: code is %d" %
inst.code)
raise NfsException("Failed to make directory: code is %d" %
inst.code)

mountcommand = 'mount.nfs'
if nfsversion == '4':
Expand All @@ -94,18 +107,18 @@ def soft_mount(mountpoint, remoteserver, remotepath, transport, timeout=0,
timeout = SOFTMOUNT_TIMEOUT

options = "soft,timeo=%d,retrans=%d,proto=%s,vers=%s" % (
timeout * 10,
SOFTMOUNT_RETRANS,
transport,
nfsversion)
timeout * 10,
SOFTMOUNT_RETRANS,
transport,
nfsversion)
options += ',acdirmin=0,acdirmax=0'

try:
util.ioretry(lambda:
util.ioretry(lambda:
util.pread([mountcommand, "%s:%s"
% (remoteserver, remotepath),
% (remoteserver, remotepath),
mountpoint, "-o", options]),
errlist=[errno.EPIPE, errno.EIO],
errlist=[errno.EPIPE, errno.EIO],
maxretry=2, nofail=True)
except util.CommandException, inst:
raise NfsException("mount failed with return code %d" % inst.code)
Expand All @@ -126,6 +139,7 @@ def unmount(mountpoint, rmmountpoint):


def scan_exports(target):
"""Scan target and return an XML DOM with target, path and accesslist."""
util.SMlog("scanning")
cmd = [SHOWMOUNT_BIN, "--no-headers", "-e", target]
dom = xml.dom.minidom.Document()
Expand All @@ -136,12 +150,12 @@ def scan_exports(target):
continue
entry = dom.createElement('Export')
element.appendChild(entry)

subentry = dom.createElement("Target")
entry.appendChild(subentry)
textnode = dom.createTextNode(target)
subentry.appendChild(textnode)

(path, access) = val.split()
subentry = dom.createElement("Path")
entry.appendChild(subentry)
Expand All @@ -155,19 +169,21 @@ def scan_exports(target):

return dom


def scan_srlist(path):
"""Scan and report SR, UUID."""
dom = xml.dom.minidom.Document()
element = dom.createElement("SRlist")
dom.appendChild(element)
for val in filter(util.match_uuid, util.ioretry( \
for val in filter(util.match_uuid, util.ioretry(
lambda: util.listdir(path))):
fullpath = os.path.join(path, val)
if not util.ioretry(lambda: util.isdir(fullpath)):
continue

entry = dom.createElement('SR')
element.appendChild(entry)

subentry = dom.createElement("UUID")
entry.appendChild(subentry)
textnode = dom.createTextNode(val)
Expand Down

0 comments on commit eaa9735

Please sign in to comment.