Implemented the following SPICE options:
- spice_bind
- spice_ip_version
- spice_password_file

Signed-off-by: Andrea Spadaccini <[email protected]>
---
 lib/constants.py         |   11 +++++++
 lib/hypervisor/hv_kvm.py |   74 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/lib/constants.py b/lib/constants.py
index f0d88d2..a803acc 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -567,6 +567,8 @@ DISK_TRANSFER_CONNECT_TIMEOUT = 60
 # Disk index separator
 DISK_SEPARATOR = _autoconf.DISK_SEPARATOR
 IP_COMMAND_PATH = _autoconf.IP_PATH
+# Makes SPICE use the default cluster IP version
+SPICE_USE_CLUSTER_DEFAULT_IP_VERSION = 0
 
 #: Key for job IDs in opcode result
 JOB_IDS_KEY = "jobs"
@@ -658,6 +660,9 @@ HV_VNC_PASSWORD_FILE = "vnc_password_file"
 HV_VNC_TLS = "vnc_tls"
 HV_VNC_X509 = "vnc_x509_path"
 HV_VNC_X509_VERIFY = "vnc_x509_verify"
+HV_KVM_SPICE_BIND = "spice_bind"
+HV_KVM_SPICE_IP_VERSION = "spice_ip_version"
+HV_KVM_SPICE_PASSWORD_FILE = "spice_password_file"
 HV_ACPI = "acpi"
 HV_PAE = "pae"
 HV_USE_BOOTLOADER = "use_bootloader"
@@ -701,6 +706,9 @@ HVS_PARAMETER_TYPES = {
   HV_VNC_TLS: VTYPE_BOOL,
   HV_VNC_X509: VTYPE_STRING,
   HV_VNC_X509_VERIFY: VTYPE_BOOL,
+  HV_KVM_SPICE_BIND: VTYPE_STRING,
+  HV_KVM_SPICE_IP_VERSION: VTYPE_INT,
+  HV_KVM_SPICE_PASSWORD_FILE: VTYPE_STRING,
   HV_ACPI: VTYPE_BOOL,
   HV_PAE: VTYPE_BOOL,
   HV_USE_BOOTLOADER: VTYPE_BOOL,
@@ -1278,6 +1286,9 @@ HVC_DEFAULTS = {
     HV_VNC_X509: "",
     HV_VNC_X509_VERIFY: False,
     HV_VNC_PASSWORD_FILE: "",
+    HV_KVM_SPICE_BIND: "",
+    HV_KVM_SPICE_IP_VERSION: SPICE_USE_CLUSTER_DEFAULT_IP_VERSION,
+    HV_KVM_SPICE_PASSWORD_FILE: "",
     HV_KVM_FLOPPY_IMAGE_PATH: "",
     HV_CDROM_IMAGE_PATH: "",
     HV_KVM_CDROM2_IMAGE_PATH: "",
diff --git a/lib/hypervisor/hv_kvm.py b/lib/hypervisor/hv_kvm.py
index 1b95d6d..74f01a0 100644
--- a/lib/hypervisor/hv_kvm.py
+++ b/lib/hypervisor/hv_kvm.py
@@ -165,6 +165,10 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     constants.HV_VNC_X509: hv_base.OPT_DIR_CHECK,
     constants.HV_VNC_X509_VERIFY: hv_base.NO_CHECK,
     constants.HV_VNC_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
+    constants.HV_KVM_SPICE_BIND: hv_base.NO_CHECK, # will be checked later
+    constants.HV_KVM_SPICE_IP_VERSION:
+      hv_base.ParamInSet(False, constants.VALID_IP_VERSIONS),
+    constants.HV_KVM_SPICE_PASSWORD_FILE: hv_base.OPT_FILE_CHECK,
     constants.HV_KVM_FLOPPY_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
     constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
     constants.HV_KVM_CDROM2_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
@@ -716,6 +720,76 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     else:
       kvm_cmd.extend(["-serial", "none"])
 
+    spice_bind = hvp[constants.HV_KVM_SPICE_BIND]
+    # Only one of VNC and SPICE can be used currently.
+    if vnc_bind_address and spice_bind:
+        raise errors.HypervisorError("both spice and vnc are configured, but"
+                                     " only one of them can be used at a"
+                                     " given time.")
+
+    if spice_bind:
+      # SPICE support is available only on KVM >= 0.14.0
+      if (v_major, v_min) < (0, 14):
+        raise errors.HypervisorError("spice is configured, but it is not"
+                                     " available in versions of KVM < 0.14")
+
+      spice_ip_version = hvp[constants.HV_KVM_SPICE_IP_VERSION]
+      if spice_ip_version == constants.SPICE_USE_CLUSTER_DEFAULT_IP_VERSION:
+        cluster_family = ssconf.SimpleStore().GetPrimaryIPFamily()
+        spice_ip_version = netutils.IpAddressFamilyToVersion(cluster_family)
+      elif not spice_ip_version in constants.VALID_IP_VERSIONS:
+        raise errors.HypervisorError("spice: The specified IP version (%d) is"
+                                     " invalid." % spice_ip_version)
+
+      if netutils.IP4Address.IsValid(spice_bind):
+        if spice_ip_version != constants.IP4_VERSION:
+          raise errors.HypervisorError("spice: got an IPv4 address (%s), but"
+                                       " the specified IP version is %d."
+                                       % (spice_bind, spice_ip_version))
+
+      elif netutils.IP6Address.IsValid(spice_bind):
+        if spice_ip_version != constants.IP6_VERSION:
+          raise errors.HypervisorError("spice: got an IPv6 address (%s), but"
+                                       " the specified IP version is %d."
+                                       % (spice_bind, spice_ip_version))
+
+      elif netutils.IsValidInterface(spice_bind):
+        addresses = netutils.GetInterfaceIpAddresses(spice_bind,
+                                                     spice_ip_version)
+        if not addresses:
+          raise errors.HypervisorError("spice: unable to get an IPv%d address"
+                                       " for %s" % (spice_ip_version, 
+                                                    spice_bind))
+        spice_bind = addresses[0]
+
+      else:
+        raise errors.HypervisorError("spice: the %s parameter must be either a"
+                                     " valid IP address or interface name" %
+                                     constants.HV_KVM_SPICE_BIND)
+
+
+      spice_arg = "addr=%s,ipv%d,port=%d" % (spice_bind,
+                                             spice_ip_version,
+                                             instance.network_port)
+
+      spice_pwd_file = hvp[constants.HV_KVM_SPICE_PASSWORD_FILE]
+      if spice_pwd_file:
+        try:
+          spice_pwd = utils.ReadOneLineFile(spice_pwd_file, strict=True)
+          spice_arg = "%s,password=%s" % (spice_arg, spice_pwd)
+        except EnvironmentError, err:
+          raise errors.HypervisorError("spice: failed to open the password"
+                                       " file %s: %s" % (spice_pwd_file, err))
+      else:
+        spice_arg = "%s,disable-ticketing" % spice_arg
+
+      logging.info("KVM: SPICE will listen on port %d" % instance.network_port)
+
+
+
+      kvm_cmd.extend(["-spice", spice_arg])
+      
+
     if hvp[constants.HV_USE_LOCALTIME]:
       kvm_cmd.extend(["-localtime"])
 
-- 
1.7.3.1

Reply via email to