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
