Hi,

LGTM.

Thanks,
Jose

On Mon, Jan 13, 2014 at 05:51:52AM -0800, [email protected] wrote:
> Hello all,
> 
> Here are a couple of patches for ganeti that make it possible to pass a 
> cdrom_image_path that is an HTTP(s)/FTP(s) url. The original patch was 
> written by Apollon Oikonomopoulos more than 2 years ago and minor 
> modifications were made by Christos Stavrakakis in order for the patches to 
> apply cleanly to 2.7+ versions. There were occasional hiccups when using 
> this feature with an old kvm version (0.12) but with version 1.1.2+ we 
> haven't noticed any problems so far.
> 
> We are currently using this functionality on our ganetimgr[1] frontend with 
> ganeti versions 2.6, 2.7 and 2.9 to give our users the ability to boot 
> their VMs without an OS and then install a custom ISO of their choice.
> 
> We (at GRNET) have been sitting on this patch for quite a while and we hope 
> it's time it gets merged upstream.
> 
> Regards,
> --
> George Kargiotakis
> GRNET NOC
> 
> [1] http://ganetimgr.readthedocs.org/en/wheezy/
> 

> commit 9fe0df635fb34ad1eb69fbb62bd91061f9154e6a
> Author: Christos Stavrakakis <[email protected]>
> Date:   Tue Oct 29 12:10:54 2013 +0200
> 
>     kvm: check that the ISO image is there if it's a URL
>     
>     Perform a simple urllib2 check on ISO images specified as URL before
>     instance start, so as to work around qemu bug #597575 [1].
>     
>     [1] https://bugs.launchpad.net/qemu/+bug/597575
>     
>     Signed-off-by: Apollon Oikonomopoulos <[email protected]>
>     Signed-off-by: Christos Stavrakakis <[email protected]>
> 
> Index: ganeti-2.9.2/lib/hypervisor/hv_kvm.py
> ===================================================================
> --- ganeti-2.9.2.orig/lib/hypervisor/hv_kvm.py        2014-01-09 
> 17:27:18.000000000 +0200
> +++ ganeti-2.9.2/lib/hypervisor/hv_kvm.py     2014-01-09 17:27:18.000000000 
> +0200
> @@ -34,6 +34,7 @@
>  import struct
>  import fcntl
>  import shutil
> +import urllib2
>  import socket
>  import stat
>  import StringIO
> @@ -164,6 +165,24 @@
>    return (ifname, tapfd)
>  
>  
> +def _CheckUrl(url):
> +  """Check if a given URL exists on the server
> +
> +  """
> +  req = urllib2.Request(url)
> +
> +  # XXX: ugly but true
> +  req.get_method = lambda: "HEAD"
> +
> +  try:
> +    resp = urllib2.urlopen(req)
> +  except urllib2.URLError:
> +    return False
> +
> +  del resp
> +  return True
> +
> +
>  class QmpMessage:
>    """QEMU Messaging Protocol (QMP) message.
>  
> @@ -1161,7 +1180,13 @@
>      iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
>      if iso_image:
>        options = ",media=cdrom"
> -      if not re.match(r'(https?|ftps?)://', iso_image):
> +      if re.match(r'(https?|ftps?)://', iso_image):
> +        # Check that the iso image is really there
> +        # See https://bugs.launchpad.net/qemu/+bug/597575
> +        if not _CheckUrl(iso_image):
> +          raise errors.HypervisorError("ISO image %s is not accessible" %
> +                                       iso_image)
> +      else:
>          options = "%s,format=raw" % options
>        # set cdrom 'if' type
>        if boot_cdrom:

> commit abfdf963d6727fd031d97864956511a30087dd11
> Author: Christos Stavrakakis <[email protected]>
> Date:   Tue Oct 29 12:09:33 2013 +0200
> 
>     Allow KVM to boot from HTTP
>     
>     New versions of KVM support booting from HTTP-hosted ISO images, via
>     libcurl. This patch adds a proper check to allow defining either a sane,
>     absolute path or an HTTP URL as an iso image path.
>     
>     Remove "format=raw" from the cdrom device options when iso_image starts
>     with "(https?|ftps?)://", to allow latest KVM versions (qemu-kvm) to boot
>     from HTTP-hosted iso images. Added FILE_OR_URL check to allow booting
>     from HTTP (kvm).
>     
>     Signed-off-by: Apollon Oikonomopoulos <[email protected]>
>     Signed-off-by: Christos Stavrakakis <[email protected]>
> 
> diff --git a/lib/hypervisor/hv_base.py b/lib/hypervisor/hv_base.py
> index c723a4d..a6e0b46 100644
> --- a/lib/hypervisor/hv_base.py
> +++ b/lib/hypervisor/hv_base.py
> @@ -83,6 +83,13 @@ def _IsMultiCpuMaskWellFormed(cpu_mask):
>  _FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
>                 os.path.isfile, "not found or not a file")
>  
> +# must be a file or a URL
> +_FILE_OR_URL_CHECK = (utils.IsNormAbsPathOrURL,
> +                      "must be an absolute normalized path or a URL",
> +                      lambda x: os.path.isfile(x) or
> +                      re.match(r'(https?|ftps?)://', x),
> +                      "not found or not a file or URL")
> +
>  # must be a directory
>  _DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
>                os.path.isdir, "not found or not a directory")
> @@ -108,6 +115,8 @@ _NONNEGATIVE_INT_CHECK = (lambda x: x >= 0, "cannot be 
> negative", None, None)
>  # nice wrappers for users
>  REQ_FILE_CHECK = (True, ) + _FILE_CHECK
>  OPT_FILE_CHECK = (False, ) + _FILE_CHECK
> +REQ_FILE_OR_URL_CHECK = (True, ) + _FILE_OR_URL_CHECK
> +OPT_FILE_OR_URL_CHECK = (False, ) + _FILE_OR_URL_CHECK
>  REQ_DIR_CHECK = (True, ) + _DIR_CHECK
>  OPT_DIR_CHECK = (False, ) + _DIR_CHECK
>  REQ_NET_PORT_CHECK = (True, ) + _NET_PORT_CHECK
> diff --git a/lib/hypervisor/hv_kvm.py b/lib/hypervisor/hv_kvm.py
> index 54bd557..01a3c52 100644
> --- a/lib/hypervisor/hv_kvm.py
> +++ b/lib/hypervisor/hv_kvm.py
> @@ -477,7 +477,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
>      constants.HV_KVM_SPICE_TLS_CIPHERS: hv_base.NO_CHECK,
>      constants.HV_KVM_SPICE_USE_VDAGENT: hv_base.NO_CHECK,
>      constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
> -    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
> +    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_OR_URL_CHECK,
>      constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
>      constants.HV_BOOT_ORDER:
>        hv_base.ParamInSet(True, constants.HT_KVM_VALID_BO_TYPES),
> @@ -1130,7 +1130,9 @@ class KVMHypervisor(hv_base.BaseHypervisor):
>  
>      iso_image = hvp[constants.HV_CDROM_IMAGE_PATH]
>      if iso_image:
> -      options = ",format=raw,media=cdrom"
> +      options = ",media=cdrom"
> +      if not re.match(r'(https?|ftps?)://', iso_image):
> +        options = "%s,format=raw" % options
>        # set cdrom 'if' type
>        if boot_cdrom:
>          actual_cdrom_type = constants.HT_DISK_IDE
> diff --git a/lib/utils/io.py b/lib/utils/io.py
> index f9675a8..47c7749 100644
> --- a/lib/utils/io.py
> +++ b/lib/utils/io.py
> @@ -23,6 +23,7 @@
>  """
>  
>  import os
> +import re
>  import logging
>  import shutil
>  import tempfile
> @@ -667,6 +668,13 @@ def IsBelowDir(root, other_path):
>    return os.path.commonprefix([prepared_root, norm_other]) == prepared_root
>  
>  
> +def IsNormAbsPathOrURL(path):
> +  """Check whether a path is absolute and normalized, or an HTTP URL.
> +
> +  """
> +  return IsNormAbsPath(path) or re.match(r'(https?|ftps?)://', path)
> +
> +
>  def PathJoin(*args):
>    """Safe-join a list of path components.
>  


-- 
Jose Antonio Lopes
Ganeti Engineering
Google Germany GmbH
Dienerstr. 12, 80331, München

Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Graham Law, Christine Elizabeth Flores
Steuernummer: 48/725/00206
Umsatzsteueridentifikationsnummer: DE813741370

Reply via email to