Ryan Harper has uploaded a new change for review.
Change subject: Add uploadIso API call for pushing ISOs into an active iso_domain via
pool
......................................................................
Add uploadIso API call for pushing ISOs into an active iso_domain via pool
The only way to get an ISO into the vdsm storage service is via ovirt-engine's
engine-iso-uploader. This requires a functioning ovirt-engine install. Instead
provide a simple API call to push the iso file out to the correct location.
Given an pool UUID, we can determine where the iso file should go via isoprefix
so use either wget or rsync to pull the iso file and place it in the pool's
iso_domain.
wget a remote iso
% vdsClient -s 0 uploadIso d3b3948a-ead6-11e1-a3a5-00fffe0000df \
http://server/path/Fedora-17-x86_64-netinst.iso
rsync in a local file
% vdsClient -s 0 uploadIso d3b3948a-ead6-11e1-a3a5-00fffe0000df \
/tmp/Fedora-17-x86_64-netinst.iso
Change-Id: Id78e46513c38789d08e63a38026b28bebb9a2b12
Signed-off-by: Ryan Harper <ryanh(a)us.ibm.com>
---
M vdsm/API.py
M vdsm/BindingXMLRPC.py
M vdsm/storage/hsm.py
M vdsm/storage/sp.py
M vdsm/storage/storage_exception.py
M vdsm_api/vdsmapi-schema.json
M vdsm_cli/vdsClient.py
7 files changed, 136 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/49/7849/1
diff --git a/vdsm/API.py b/vdsm/API.py
index 827f73b..734f40d 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -956,6 +956,9 @@
return self._irs.upgradeStoragePool(self._UUID,
targetDomVersion)
+ def uploadIso(self, srcPath, method):
+ return self._irs.uploadIso(self._UUID, srcPath, method)
+
def validateStorageServerConnection(self, domainType,
connectionParams):
return self._irs.validateStorageServerConnection(domainType,
diff --git a/vdsm/BindingXMLRPC.py b/vdsm/BindingXMLRPC.py
index 826c125..ca92779 100644
--- a/vdsm/BindingXMLRPC.py
+++ b/vdsm/BindingXMLRPC.py
@@ -563,6 +563,10 @@
pool = API.StoragePool(spUUID)
return pool.upgrade(targetDomVersion)
+ def poolUploadIso(self, spUUID, srcPath, method):
+ pool = API.StoragePool(spUUID)
+ return pool.uploadIso(srcPath, method)
+
def poolValidateStorageServerConnection(self, domType, spUUID, conList,
options=None):
pool = API.StoragePool(spUUID)
@@ -809,6 +813,7 @@
(self.poolSpmStart, 'spmStart'),
(self.poolSpmStop, 'spmStop'),
(self.poolUpgrade, 'upgradeStoragePool'),
+ (self.poolUploadIso, 'uploadIso'),
(self.poolValidateStorageServerConnection,
'validateStorageServerConnection'),
(self.poolUpdateVMs, 'updateVM'),
diff --git a/vdsm/storage/hsm.py b/vdsm/storage/hsm.py
index 1e9311b..2fb9fae 100644
--- a/vdsm/storage/hsm.py
+++ b/vdsm/storage/hsm.py
@@ -1189,6 +1189,19 @@
pool = self.getPool(spUUID)
pool.uploadVolume(sdUUID, imgUUID, volUUID, srcPath, size,
method="rsync")
+ @public
+ def uploadIso(self, spUUID, srcPath, method):
+ """
+ Uploads an ISO to <pool UUID>'s iso domain
+
+ :param spUUID: The UUID of the storage pool that will contain the new iso.
+ :type spUUID: UUID
+ :param method: The desired method of upload. Currently only *'wget'* and
*'rsync'* are supported.
+ :type method: str
+ """
+ vars.task.getSharedLock(STORAGE, spUUID)
+ pool = self.getPool(spUUID)
+ pool.uploadIso(srcPath, method)
@public
def createVolume(self, sdUUID, spUUID, imgUUID, size, volFormat, preallocate,
diskType, volUUID, desc, srcImgUUID=volume.BLANK_UUID, srcVolUUID=volume.BLANK_UUID):
diff --git a/vdsm/storage/sp.py b/vdsm/storage/sp.py
index c10974c..1c9dec7 100644
--- a/vdsm/storage/sp.py
+++ b/vdsm/storage/sp.py
@@ -2004,6 +2004,69 @@
except:
self.log.warning("SP %s SD %s img %s Vol %s - teardown
failed")
+
+ def uploadIso(self, srcPath, method):
+ self.log.info("uploadIso - srcPath=%s method=%s"%(srcPath, method))
+
+ # find the iso domain within the pool
+ info = self.getInfo()['info']
+ if 'isoprefix' in info.keys() and len(info['isoprefix']) > 0:
+ targetPath = info['isoprefix']
+ else:
+ self.log.error("uploadIso - target pool(%s) does not"
+ "have an ISO domain" %(self.spUUID))
+ raise se.StoragePoolNoIsoDomain()
+
+ self.log.info("uploadIso - targetPath=%s"%(targetPath))
+ rc = 0
+
+ # we can infer the method to use by inspection of srcPath
+ if len(method) == 0:
+ if srcPath.startswith("http://"):
+ method = "wget"
+ else:
+ method = "rsync"
+
+ try:
+ if method.lower() == "wget":
+ if not srcPath.startswith("http://"):
+ self.log.error("uploadIso - wget method requires HTTP
URL")
+ raise se.InvalidParameterException('srcPath mismatch with'
+ ' method', method)
+
+ outFile = os.path.join(targetPath, os.path.basename(srcPath))
+ cmd = [constants.EXT_WGET, "-O", outFile, srcPath]
+ (rc, out, err) = misc.execCmd(cmd, sudo=False)
+
+ if rc:
+ self.log.error("uploadIso - error while trying to
retrieve:"
+ "%s into: %s, stderr: %s" % (srcPath,
+ targetPath,
+ err))
+ raise se.VolumeCopyError(srcPath, err)
+ elif method.lower() == "rsync":
+ if srcPath.startswith("http://"):
+ self.log.error("uploadIso - rsync method cannot use"
+ "HTTP URL")
+ raise se.InvalidParameterException('srcPath mismatch with'
+ ' method', method)
+ cmd = [constants.EXT_RSYNC, "-aq", srcPath, targetPath]
+ (rc, out, err) = misc.execCmd(cmd, sudo=False)
+
+ if rc:
+ self.log.error("uploadIso - error while trying to copy:"
+ "%s into: %s, stderr: %s" % (srcPath,
+ targetPath,
+ err))
+ raise se.VolumeCopyError(srcPath, err)
+ else:
+ self.log.error("uploadIso - method '%s' not supported",
method)
+ raise se.InvalidParameterException('method', method)
+
+ finally:
+ if rc == 0:
+ self.log.info("uploadIso - completed via %s", method)
+
def preDeleteRename(self, sdUUID, imgUUID):
repoPath = os.path.join(self.storage_repository, self.spUUID)
return image.Image(repoPath).preDeleteRename(sdUUID, imgUUID)
diff --git a/vdsm/storage/storage_exception.py b/vdsm/storage/storage_exception.py
index f1edad4..88ac2d5 100644
--- a/vdsm/storage/storage_exception.py
+++ b/vdsm/storage/storage_exception.py
@@ -508,6 +508,10 @@
code = 330
message = "Cannot get files list"
+class StoragePoolNoIsoDomain(StorageException):
+ code = 331
+ message = "No ISO Domain available in Storage Pool"
+
#################################################
# Domains Exceptions
#################################################
diff --git a/vdsm_api/vdsmapi-schema.json b/vdsm_api/vdsmapi-schema.json
index a773177..d898d0a 100644
--- a/vdsm_api/vdsmapi-schema.json
+++ b/vdsm_api/vdsmapi-schema.json
@@ -3309,6 +3309,38 @@
'size': 'int', 'method':
'UploadVolumeMethod'}}
##
+# @UploadIsoMethod:
+#
+# An enumeration of uploadIso methods.
+#
+# @wget: Fetch data using the wget command
+#
+# @rsync: Fetch data using the rsync command
+#
+# Since: 4.10.0
+##
+{'enum': 'UploadIsoMethod', 'data': ['wget',
'rsync']}
+
+##
+# @StoragePool.uploadIso:
+#
+# Upload an ISO file into a Storage Pool from a remote location.
+#
+# @spUUID: The UUID of the pool in which the ISO will be uploaded
+#
+# @srcPath: The remote location of the ISO data. Must be in a format that
+# can be understood by the command indicated in @method.
+#
+# @method: The method (command) to use to upload the data
+#
+# Since: 4.10.0
+##
+{'command': {'class': 'StoragePool', 'name':
'uploadIso'},
+ 'data': {'spUUID': 'UUID', 'srcPath': 'str',
+ 'method': 'UploadVolumeMethod'}}
+
+
+##
# @StorageDomain.validate:
#
# Check that the Storage Domain is accessible.
diff --git a/vdsm_cli/vdsClient.py b/vdsm_cli/vdsClient.py
index ff7ccc8..c1f5268 100644
--- a/vdsm_cli/vdsClient.py
+++ b/vdsm_cli/vdsClient.py
@@ -962,6 +962,17 @@
return status['status']['code'],
status['status']['message']
return 0, ''
+ def uploadIso(self, args):
+ spUUID = args[0]
+ srcPath = args[1]
+ method = ''
+ if len(args) > 2:
+ method = args[2]
+ status = self.s.uploadIso(spUUID, srcPath, method)
+ if status['status']['code']:
+ return status['status']['code'],
status['status']['message']
+ return 0, ''
+
def uploadVolume(self, args):
sdUUID = args[0]
spUUID = args[1]
@@ -2048,6 +2059,11 @@
'<new disk size>',
'Extend volume (SAN only)'
)),
+ 'uploadIso': (serv.uploadIso,
+ ('<spUUID> <srcPath> [<method>]',
+ 'Upload ISO file into the specified storage pool.'
+ ' <method> is one of [wget|rsync] and is
optional'
+ )),
'uploadVolume': (serv.uploadVolume,
('<sdUUID> <spUUID> <imgUUID>
<volUUID> <srcPath> '
'<size>',
--
To view, visit
http://gerrit.ovirt.org/7849
To unsubscribe, visit
http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id78e46513c38789d08e63a38026b28bebb9a2b12
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Ryan Harper <ryanh(a)us.ibm.com>