On Wed, Apr 20, 2022 at 05:14:26PM +0200, Tomáš Golembiovský wrote:
> oVirt API call for VM creation finishes before the VM is actually
> created. Entities may be still locked after virt-v2v terminates and if
> user tries to perform (scripted) actions after virt-v2v those operations
> may fail. To prevent this it is useful to monitor the task and wait for
> the completion. This will also help to prevent some corner case
> scenarios (that would be difficult to debug) when the VM creation job
> fails after virt-v2v already termintates with success.
> 
> Thanks: Nir Soffer
> Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1985827
> Signed-off-by: Tomáš Golembiovský <tgole...@redhat.com>
> Reviewed-by: Arik Hadas <aha...@redhat.com>
> Reviewed-by: Nir Soffer <nsof...@redhat.com>

Thanks Tomas, this works for me and I've pushed it just now:

   06e69bae25..291edb363e  master -> master

Rich.

>  output/rhv-upload-createvm.py                 | 57 ++++++++++++++++++-
>  .../ovirtsdk4/__init__.py                     | 10 +++-
>  .../ovirtsdk4/types.py                        | 19 +++++++
>  3 files changed, 84 insertions(+), 2 deletions(-)
> 
> Changes in v3:
> 
> - this time really increased sleep and decreased timeout
> 
> diff --git a/output/rhv-upload-createvm.py b/output/rhv-upload-createvm.py
> index 50bb7e34..8887c52b 100644
> --- a/output/rhv-upload-createvm.py
> +++ b/output/rhv-upload-createvm.py
> @@ -19,12 +19,54 @@
>  import json
>  import logging
>  import sys
> +import time
> +import uuid
>  
>  from urllib.parse import urlparse
>  
>  import ovirtsdk4 as sdk
>  import ovirtsdk4.types as types
>  
> +
> +def debug(s):
> +    if params['verbose']:
> +        print(s, file=sys.stderr)
> +        sys.stderr.flush()
> +
> +
> +def jobs_completed(system_service, correlation_id):
> +    jobs_service = system_service.jobs_service()
> +
> +    try:
> +        jobs = jobs_service.list(
> +            search="correlation_id=%s" % correlation_id)
> +    except sdk.Error as e:
> +        debug(
> +            "Error searching for jobs with correlation id %s: %s" %
> +            (correlation_id, e))
> +        # We don't know, assume that jobs did not complete yet.
> +        return False
> +
> +    # STARTED is the only "in progress" status, anything else means the job
> +    # has already terminated.
> +    if all(job.status != types.JobStatus.STARTED for job in jobs):
> +        failed_jobs = [(job.description, str(job.status))
> +                       for job in jobs
> +                       if job.status != types.JobStatus.FINISHED]
> +        if failed_jobs:
> +            raise RuntimeError(
> +                "Failed to create a VM! Failed jobs: %r" % failed_jobs)
> +        return True
> +    else:
> +        running_jobs = [(job.description, str(job.status)) for job in jobs]
> +        debug("Some jobs with correlation id %s are running: %s" %
> +              (correlation_id, running_jobs))
> +        return False
> +
> +
> +# Seconds to wait for the VM import job to complete in oVirt.
> +timeout = 3 * 60
> +
>  # Parameters are passed in via a JSON doc from the OCaml code.
>  # Because this Python code ships embedded inside virt-v2v there
>  # is no formal API here.
> @@ -67,6 +109,7 @@ system_service = connection.system_service()
>  cluster = 
> system_service.clusters_service().cluster_service(params['rhv_cluster_uuid'])
>  cluster = cluster.get()
>  
> +correlation_id = str(uuid.uuid4())
>  vms_service = system_service.vms_service()
>  vm = vms_service.add(
>      types.Vm(
> @@ -77,5 +120,17 @@ vm = vms_service.add(
>                  data=ovf,
>              )
>          )
> -    )
> +    ),
> +    query={'correlation_id': correlation_id},
>  )
> +
> +# Wait for the import job to finish.
> +endt = time.monotonic() + timeout
> +while True:
> +    time.sleep(10)
> +    if jobs_completed(system_service, correlation_id):
> +        break
> +    if time.monotonic() > endt:
> +        raise RuntimeError(
> +            "Timed out waiting for VM creation!"
> +            " Jobs still running for correlation id %s" % correlation_id)
> diff --git a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py 
> b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
> index 0d8f33b3..e33d0714 100644
> --- a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
> +++ b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/__init__.py
> @@ -59,6 +59,9 @@ class SystemService(object):
>      def disks_service(self):
>          return DisksService()
>  
> +    def jobs_service(self):
> +        return JobsService()
> +
>      def image_transfers_service(self):
>          return ImageTransfersService()
>  
> @@ -104,6 +107,11 @@ class DisksService(object):
>          return DiskService(disk_id)
>  
>  
> +class JobsService(object):
> +    def list(self, search=None):
> +        return [types.Job()]
> +
> +
>  class ImageTransferService(object):
>      def __init__(self):
>          self._finalized = False
> @@ -135,7 +143,7 @@ class StorageDomainsService(object):
>  
>  
>  class VmsService(object):
> -    def add(self, vm):
> +    def add(self, vm, query=None):
>          return vm
>  
>      def list(self, search=None):
> diff --git a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py 
> b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
> index 5707fa3e..38d89573 100644
> --- a/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
> +++ b/tests/test-v2v-o-rhv-upload-module/ovirtsdk4/types.py
> @@ -141,6 +141,25 @@ class Initialization(object):
>          pass
>  
>  
> +class JobStatus(Enum):
> +    ABORTED = "aborted"
> +    FAILED = "failed"
> +    FINISHED = "finished"
> +    STARTED = "started"
> +    UNKNOWN = "unknown"
> +
> +    def __init__(self, image):
> +        self._image = image
> +
> +    def __str__(self):
> +        return self._image
> +
> +
> +class Job(object):
> +    description = "Fake job"
> +    status = JobStatus.FINISHED
> +
> +
>  class StorageDomain(object):
>      def __init__(self, name=None):
>          pass
> -- 
> 2.35.1
> 
> _______________________________________________
> Libguestfs mailing list
> Libguestfs@redhat.com
> https://listman.redhat.com/mailman/listinfo/libguestfs

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
Fedora Windows cross-compiler. Compile Windows programs, test, and
build Windows installers. Over 100 libraries supported.
http://fedoraproject.org/wiki/MinGW
_______________________________________________
Libguestfs mailing list
Libguestfs@redhat.com
https://listman.redhat.com/mailman/listinfo/libguestfs

Reply via email to