Skip to content

Commit

Permalink
Merge 81a73f7 into bb2b479
Browse files Browse the repository at this point in the history
  • Loading branch information
BenSimsCitrix committed Nov 6, 2019
2 parents bb2b479 + 81a73f7 commit 6b2e995
Show file tree
Hide file tree
Showing 11 changed files with 564 additions and 162 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ SM_LIBS += scsiutil
SM_LIBS += scsi_host_rescan
SM_LIBS += vhdutil
SM_LIBS += lvhdutil
SM_LIBS += cifutils
SM_LIBS += xs_errors
SM_LIBS += nfs
SM_LIBS += devscan
Expand Down
115 changes: 40 additions & 75 deletions drivers/ISOSR.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 @@ -21,13 +21,14 @@
import nfs
import os, re
import xs_errors
import cifutils

CAPABILITIES = ["VDI_CREATE", "VDI_DELETE", "VDI_ATTACH", "VDI_DETACH",
CAPABILITIES = ["VDI_CREATE", "VDI_DELETE", "VDI_ATTACH", "VDI_DETACH",
"SR_SCAN", "SR_ATTACH", "SR_DETACH"]

CONFIGURATION = \
[ [ 'location', 'path to mount (required) (e.g. server:/path)' ],
[ 'options',
[ [ 'location', 'path to mount (required) (e.g. server:/path)' ],
[ 'options',
'extra options to pass to mount (deprecated) (e.g. \'-o ro\')' ],
[ 'type','cifs or nfs'],
nfs.NFS_VERSION]
Expand Down Expand Up @@ -60,7 +61,7 @@ def is_image_utf8_compatible(s):
except UnicodeDecodeError, e:
util.SMlog("WARNING: This string is not UTF-8 compatible.")
return False
return True
return True

def tools_iso_name(filename):
# The tools ISO used have a "xs-" prefix in its name.
Expand Down Expand Up @@ -152,7 +153,7 @@ def _loadvdis(self):
vdi.sm_config['created'] = sm_config['created']
vdi.read_only = False

# Now for the main functions:
# Now for the main functions:
def handles(type):
"""Do we handle this type?"""
if type == TYPE:
Expand All @@ -161,7 +162,7 @@ def handles(type):
handles = staticmethod(handles)

def content_type(self, sr_uuid):
"""Returns the content_type XML"""
"""Returns the content_type XML"""
return super(ISOSR, self).content_type(sr_uuid)

vdi_path_regex = re.compile("[a-z0-9.-]+\.(iso|img)", re.I)
Expand Down Expand Up @@ -209,7 +210,7 @@ def load(self, sr_uuid):
# Verify the target address
self._checkTargetStr(self.dconf['location'])
self.mountpoint = os.path.join(SR.MOUNT_BASE, sr_uuid)

# Add on the iso_path value if there is one
if self.dconf.has_key("iso_path"):
iso_path = util.to_plain_string(self.dconf['iso_path'])
Expand All @@ -230,11 +231,10 @@ def load(self, sr_uuid):

# Some info we need:
self.sr_vditype = 'phy'
self.credentials = None

def delete(self, sr_uuid):
pass

def attach(self, sr_uuid):
"""Std. attach"""
# Very-Legacy mode means the ISOs are in the local fs - so no need to attach.
Expand All @@ -243,7 +243,7 @@ def attach(self, sr_uuid):
if not os.path.exists(self.mountpoint):
raise xs_errors.XenError('ISOLocalPath')
return

# Check whether we're already mounted
if self._checkmount():
return
Expand All @@ -254,7 +254,6 @@ def attach(self, sr_uuid):

mountcmd=[]
location = util.to_plain_string(self.dconf['location'])
self.credentials = os.path.join("/tmp", util.gen_uuid())
# TODO: Have XC standardise iso type string
protocol = 'nfs_iso'
options = ''
Expand All @@ -268,7 +267,7 @@ def attach(self, sr_uuid):
options = self.dconf['options'].split(' ')
if protocol == 'cifs':
options = filter(lambda x: x != "", options)
else:
else:
options = self.getNFSOptions(options)

# SMB options are passed differently for create via
Expand Down Expand Up @@ -305,7 +304,6 @@ def attach(self, sr_uuid):
# Check the validity of 'smbversion'.
# Raise an exception for any invalid version.
if self.smbversion not in [SMB_VERSION_1, SMB_VERSION_3]:
self._cleanupcredentials()
raise xs_errors.XenError('ISOInvalidSMBversion')

# Attempt mounting
Expand Down Expand Up @@ -344,26 +342,23 @@ def attach(self, sr_uuid):
mountcmd.extend(options)
self.mountOverSMB(mountcmd)
else:
self._cleanupcredentials()
raise xs_errors.XenError(
'ISOMountFailure', opterr=inst.reason)
else:
util.SMlog('ISOSR mount over smb 1.0')
self.mountOverSMB(mountcmd)
except util.CommandException, inst:
self._cleanupcredentials()
if not self.is_smbversion_specified:
raise xs_errors.XenError(
'ISOMountFailure', opterr=smb3_fail_reason)
else:
raise xs_errors.XenError(
'ISOMountFailure', opterr=inst.reason)
self._cleanupcredentials()

# Check the iso_path is accessible
if not self._checkmount():
self.detach(sr_uuid)
raise xs_errors.XenError('ISOSharenameFailure')
raise xs_errors.XenError('ISOSharenameFailure')

def getSMBVersionFromOptions(self, options):
"""Extract SMB version from options """
Expand All @@ -384,7 +379,10 @@ def getSMBVersion(self):

def mountOverSMB(self, mountcmd):
"""This function raises util.CommandException"""
util.pread(mountcmd, True)
new_env, domain = cifutils.getCIFCredentials(self.dconf, self.session,
prefix="cifs")

util.pread(mountcmd, True, new_env=new_env)
try:
if not self.is_smbversion_specified:
# Store the successful smb version in PBD config
Expand Down Expand Up @@ -421,10 +419,19 @@ def appendCIFSMountOptions(self, mountcmd):
"""Append options to mount.cifs"""
options = []
try:
options.append(self.getCIFSPasswordOptions())
options.append(self.getCacheOptions())
options.append('guest')

if not cifutils.containsCredentials(self.dconf, prefix="cifs"):
options.append('guest')

options.append(self.getSMBVersion())

username, domain = (
cifutils.splitDomainAndUsername(self.dconf['username'])
)

if domain:
options.append('domain=' + domain)
except:
util.SMlog("Exception while attempting to append mount options")
raise
Expand All @@ -438,54 +445,12 @@ def getCacheOptions(self):
"""Pass cache options to mount.cifs"""
return "cache=none"

def getCIFSPasswordOptions(self):
if self.dconf.has_key('username') \
and (self.dconf.has_key('cifspassword') or self.dconf.has_key('cifspassword_secret')):
dom_username = self.dconf['username'].split('\\')
if len(dom_username) == 1:
domain = None
username = dom_username[0]
elif len(dom_username) == 2:
domain = dom_username[0]
username = dom_username[1]
else:
err_str = ("A maximum of 2 tokens are expected "
"(<domain>\<username>). {} were given."
.format(len(dom_username)))
util.SMlog('CIFS ISO SR mount error: ' + err_str)
raise xs_errors.XenError('ISOMountFailure', opterr=err_str)

if self.dconf.has_key('cifspassword_secret'):
password = util.get_secret(self.session, self.dconf['cifspassword_secret'])
else:
password = self.dconf['cifspassword']

domain = util.to_plain_string(domain)
username = util.to_plain_string(username)
password = util.to_plain_string(password)

cred_str = 'username={}\npassword={}\n'.format(username, password)

if domain:
cred_str += 'domain={}\n'.format(domain)

# Open credentials file and truncate
f = open(self.credentials, 'w')
f.write(cred_str)
f.close()
credentials = "credentials=%s" % self.credentials
return credentials

def _cleanupcredentials(self):
if self.credentials and os.path.exists(self.credentials):
os.unlink(self.credentials)

def detach(self, sr_uuid):
"""Std. detach"""
# This handles legacy mode too, so no need to check
if not self._checkmount():
return
return

try:
util.pread(["umount", self.mountpoint]);
except util.CommandException, inst:
Expand All @@ -496,11 +461,11 @@ def scan(self, sr_uuid):
"""Scan: see _loadvdis"""
if not util.isdir(self.path):
raise xs_errors.XenError('SRUnavailable', \
opterr = 'no such directory %s' % self.path)
opterr = 'no such directory %s' % self.path)

if (not self.dconf.has_key('legacy_mode')) and (not self._checkmount()):
raise xs_errors.XenError('SRUnavailable', \
opterr = 'directory not mounted: %s' % self.path)
opterr = 'directory not mounted: %s' % self.path)

#try:
if not self.vdis:
Expand Down Expand Up @@ -595,7 +560,7 @@ def create(self, sr_uuid, size):

self.detach(sr_uuid)


class ISOVDI(VDI.VDI):
def load(self, vdi_uuid):
# Nb, in the vdi_create call, the filename is unset, so the following
Expand All @@ -614,7 +579,7 @@ def __init__(self, mysr, filename):
VDI.VDI.__init__(self, mysr, None)
self.location = filename
self.filename = filename
self.read_only = True
self.read_only = True
self.label = filename
self.sm_config = {}
if mysr.dconf.has_key("legacy_mode"):
Expand Down Expand Up @@ -644,7 +609,7 @@ def detach(self, sr_uuid, vdi_uuid):

def attach(self, sr_uuid, vdi_uuid):
try:
os.stat(self.path)
os.stat(self.path)
return super(ISOVDI, self).attach(sr_uuid, vdi_uuid)
except:
raise xs_errors.XenError('VDIMissing')
Expand Down Expand Up @@ -689,7 +654,7 @@ def delete(self, sr_uuid, vdi_uuid):
raise xs_errors.XenError('VDIDelete')

# delete, update, introduce unimplemented. super class will raise
# exceptions
# exceptions

if __name__ == '__main__':
SRCommand.run(ISOSR, DRIVER_INFO)
Expand Down
Loading

0 comments on commit 6b2e995

Please sign in to comment.