Change in vdsm[master]: v2v: Job related actions
shavivi at redhat.com
shavivi at redhat.com
Mon Mar 30 13:22:18 UTC 2015
Shahar Havivi has uploaded a new change for review.
Change subject: v2v: Job related actions
......................................................................
v2v: Job related actions
Added few job related actions:
Delete job
Abort Job
Get ovf (jobs output)
Change-Id: I9a58583a88e2f17ce0847626cd601efbe1a00ac9
Signed-off-by: Shahar Havivi <shaharh at redhat.com>
---
M client/vdsClient.py
M vdsm/API.py
M vdsm/rpc/BindingXMLRPC.py
M vdsm/rpc/Bridge.py
M vdsm/rpc/vdsmapi-schema.json
M vdsm/v2v.py
6 files changed, 181 insertions(+), 1 deletion(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/61/39361/1
diff --git a/client/vdsClient.py b/client/vdsClient.py
index 9704fdb..b5be5a1 100755
--- a/client/vdsClient.py
+++ b/client/vdsClient.py
@@ -1928,6 +1928,26 @@
print "v2v job started"
return status['status']['code'], status['status']['message']
+ def getConvertedVm(self, args):
+ if len(args) != 1:
+ raise ValueError('Wrong number of arguments')
+ status = self.s.getConvertedVm(args[0])
+ if status['status']['code'] == 0:
+ print status['ovf']
+ return status['status']['code'], status['status']['message']
+
+ def abortV2VJob(self, args):
+ if len(args) != 1:
+ raise ValueError('Wrong number of arguments')
+ status = self.s.abortV2VJob(args[0])
+ return status['status']['code'], status['status']['message']
+
+ def deleteV2VJob(self, args):
+ if len(args) != 1:
+ raise ValueError('Wrong number of arguments')
+ status = self.s.deleteV2VJob(args[0])
+ return status['status']['code'], status['status']['message']
+
if __name__ == '__main__':
if _glusterEnabled:
serv = ge.GlusterService()
@@ -2811,6 +2831,21 @@
'If auth argument is provided, password will be '
'ignored (yet has to be specified, ie -)'
)),
+ 'getConvertedVm': (
+ serv.getConvertedVm, (
+ '<jobId>',
+ 'Return converted VMs OVF'
+ )),
+ 'abortV2VJob': (
+ serv.abortV2VJob, (
+ '<jobId>',
+ 'Abort running V2V convert process'
+ )),
+ 'deleteV2VJob': (
+ serv.deleteV2VJob, (
+ '<jobId>',
+ 'Delete V2v job when job is done'
+ )),
}
if _glusterEnabled:
commands.update(ge.getGlusterCmdDict(serv))
diff --git a/vdsm/API.py b/vdsm/API.py
index e9454b4..f2bbfe9 100644
--- a/vdsm/API.py
+++ b/vdsm/API.py
@@ -1410,6 +1410,15 @@
return v2v.convert(uri, username, password, vmProperties, jobId,
self._cif)
+ def getConvertedVm(self, jobId):
+ return v2v.get_converted_vm(jobId)
+
+ def deleteV2VJob(self, jobId):
+ return v2v.delete_job(jobId)
+
+ def abortV2VJob(self, jobId):
+ return v2v.abort_job(jobId)
+
# Networking-related functions
def setupNetworks(self, networks, bondings, options):
"""Add a new network to this vds, replacing an old one."""
diff --git a/vdsm/rpc/BindingXMLRPC.py b/vdsm/rpc/BindingXMLRPC.py
index 9aefe9f..68d8b44 100644
--- a/vdsm/rpc/BindingXMLRPC.py
+++ b/vdsm/rpc/BindingXMLRPC.py
@@ -370,6 +370,18 @@
return api.convertVmFromExternalSystem(uri, username, password,
vmProperties, jobId)
+ def getConvertedVm(self, jobId):
+ api = API.Global()
+ return api.getConvertedVm(jobId)
+
+ def abortV2VJob(self, jobId):
+ api = API.Global()
+ return api.abortV2VJob(jobId)
+
+ def deleteV2VJob(self, jobId):
+ api = API.Global()
+ return api.deleteV2VJob(jobId)
+
def vmPause(self, vmId):
vm = API.VM(vmId)
return vm.pause()
@@ -1044,7 +1056,10 @@
(self.vmGetIoTunePolicy, 'getIoTunePolicy'),
(self.getExternalVMs, 'getExternalVMs'),
(self.convertVmFromExternalSystem,
- 'convertVmFromExternalSystem'))
+ 'convertVmFromExternalSystem'),
+ (self.getConvertedVm, 'getConvertedVm'),
+ (self.abortV2VJob, 'abortV2VJob'),
+ (self.deleteV2VJob, 'deleteV2VJob'))
def getIrsMethods(self):
return ((self.domainActivate, 'activateStorageDomain'),
diff --git a/vdsm/rpc/Bridge.py b/vdsm/rpc/Bridge.py
index 3adb71b..30c9579 100644
--- a/vdsm/rpc/Bridge.py
+++ b/vdsm/rpc/Bridge.py
@@ -403,6 +403,7 @@
'Host_getDeviceList': {'ret': 'devList'},
'Host_getDevicesVisibility': {'ret': 'visible'},
'Host_getExternalVMs': {'ret': 'vmList'},
+ 'Host_getConvertedVm': {'ret': 'ovf'},
'Host_getHardwareInfo': {'ret': 'info'},
'Host_getLVMVolumeGroups': {'ret': 'vglist'},
'Host_getRoute': {'ret': 'info'},
diff --git a/vdsm/rpc/vdsmapi-schema.json b/vdsm/rpc/vdsmapi-schema.json
index 7a8b2f9..c22ab94 100644
--- a/vdsm/rpc/vdsmapi-schema.json
+++ b/vdsm/rpc/vdsmapi-schema.json
@@ -3816,6 +3816,43 @@
'vmProperties': 'ExternalVmInfo', 'jobId': 'UUID'}}
##
+# @Host.getConvertedVm:
+#
+# Return OVF string that created via convertVmFromExternalSystem call
+#
+# @jobId: UUID to identify the job that created in convertVmFromExternalSystem
+#
+# Since: 4.17.0
+##
+{'command': {'class': 'Host', 'name': 'getConvertedVm'},
+ 'data': {'jobId': 'UUID'}
+ 'returns': 'str'}
+
+##
+# @Host.abortV2VJob:
+#
+# Abort V2V importing process
+#
+# @jobId: UUID to identify the job that created in convertVmFromExternalSystem
+#
+# Since: 4.17.0
+##
+{'command': {'class': 'Host', 'name': 'abortV2VJob'},
+ 'data': {'jobId': 'UUID'}}
+
+##
+# @Host.deleteV2VJob:
+#
+# Delete V2V job when job is done or stop due to errors
+#
+# @jobId: UUID to identify the job that created in convertVmFromExternalSystem
+#
+# Since: 4.17.0
+##
+{'command': {'class': 'Host', 'name': 'deleteV2VJob'},
+ 'data': {'jobId': 'UUID'}}
+
+##
# @VMFullInfo:
#
# Full information about VM.
diff --git a/vdsm/v2v.py b/vdsm/v2v.py
index 9b63f70..a0370f7 100644
--- a/vdsm/v2v.py
+++ b/vdsm/v2v.py
@@ -89,6 +89,21 @@
err_name = 'V2VJobExists'
+class NoSuchJob(V2VError):
+ ''' Job not exists in _jobs collection '''
+ err_name = 'V2VNoSuchJob'
+
+
+class JobNotDone(V2VError):
+ ''' Import process still in progress '''
+ err_name = 'V2VJobNotDone'
+
+
+class NoSuchOvf(V2VError):
+ ''' Ovf path is not exists in /var/run/vdsm/v2v/ '''
+ err_name = 'V2VNoSuchOvf'
+
+
class VolumeError(RuntimeError):
''' Error preparing volume '''
@@ -150,6 +165,39 @@
return {'status': doneCode}
+def get_converted_vm(job_id):
+ try:
+ job = _get_job(job_id)
+ _validate_job_done(job)
+ ovf = _read_ovf(job_id)
+ except V2VError as e:
+ logging.warning('Converted VM error %s', e)
+ return errCode[e.err_name]
+ return {'status': doneCode, 'ovf': ovf}
+
+
+def delete_job(job_id):
+ try:
+ job = _get_job(job_id)
+ _validate_job_finished(job)
+ _remove_job(job_id)
+ except V2VError as e:
+ logging.warning('Error deleting job: %s, error: %s', job_id, e)
+ return errCode[e.err_name]
+ return {'status': doneCode}
+
+
+def abort_job(job_id):
+ try:
+ job = _get_job(job_id)
+ job.abort()
+ _remove_job(job_id)
+ except V2VError as e:
+ logging.warning('Error aboring job: %s, error: %s', job_id, e)
+ return errCode[e.err_name]
+ return {'status': doneCode}
+
+
def jobs():
ret = {}
with _lock:
@@ -162,6 +210,17 @@
'progress': job.progress
}
return ret
+
+
+def _read_ovf(job_id):
+ file_name = os.path.join(_V2V_DIR, "%s.ovf" % job_id)
+ try:
+ with open(file_name, 'r') as f:
+ return f.read()
+ except IOError as e:
+ if e.errno != errno.ENOENT:
+ raise
+ raise NoSuchOvf("No such ovf %r" % file_name)
def _add_job(job_id, job):
@@ -179,6 +238,30 @@
return path.rsplit(os.sep, 3)[0]
+def _get_job(job_id):
+ with _lock:
+ if job_id not in _jobs:
+ raise NoSuchJob()
+ return _jobs[job_id]
+
+
+def _remove_job(job_id):
+ with _lock:
+ if job_id not in _jobs:
+ raise NoSuchJob("No such job %r" % job_id)
+ del _jobs[job_id]
+
+
+def _validate_job_done(job):
+ if job.status != STATUS.DONE:
+ raise JobNotDone("Job %r is %s" % (job.id, job.status))
+
+
+def _validate_job_finished(job):
+ if job.status not in (STATUS.DONE, STATUS.FAILED, STATUS.ABORTED):
+ raise JobNotDone("Job %r is %s" % (job.id, job.status))
+
+
class ImportVm(object):
ABORT_RETRIES = 3
ABORT_DELAY = 10
--
To view, visit https://gerrit.ovirt.org/39361
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9a58583a88e2f17ce0847626cd601efbe1a00ac9
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Shahar Havivi <shavivi at redhat.com>
More information about the vdsm-patches
mailing list