support: Drop open coded dict, use classes

This commit is contained in:
Cole Robinson 2013-08-09 15:56:18 -04:00
parent 3e158b80bf
commit d328b311ec

View File

@ -23,342 +23,6 @@ import libvirt
from virtinst import util from virtinst import util
# Flags for check_conn_support
(SUPPORT_CONN_STORAGE,
SUPPORT_CONN_FINDPOOLSOURCES,
SUPPORT_CONN_NODEDEV,
SUPPORT_CONN_KEYMAP_AUTODETECT,
SUPPORT_CONN_GETHOSTNAME,
SUPPORT_CONN_DOMAIN_VIDEO,
SUPPORT_CONN_NETWORK,
SUPPORT_CONN_INTERFACE,
SUPPORT_CONN_MAXVCPUS_XML,
SUPPORT_CONN_STREAM,
SUPPORT_CONN_GETVERSION,
SUPPORT_CONN_LIBVERSION,
SUPPORT_CONN_LISTALLDOMAINS,
SUPPORT_CONN_LISTALLNETWORKS,
SUPPORT_CONN_LISTALLSTORAGEPOOLS,
SUPPORT_CONN_LISTALLINTERFACES) = range(1, 17)
# Flags for check_domain_support
(SUPPORT_DOMAIN_GETVCPUS,
SUPPORT_DOMAIN_XML_SECURE,
SUPPORT_DOMAIN_XML_INACTIVE,
SUPPORT_DOMAIN_MANAGED_SAVE,
SUPPORT_DOMAIN_MIGRATE_DOWNTIME,
SUPPORT_DOMAIN_JOB_INFO,
SUPPORT_DOMAIN_MAXVCPUS_XML,
SUPPORT_DOMAIN_CONSOLE_STREAM,
SUPPORT_DOMAIN_SET_METADATA,
SUPPORT_DOMAIN_CPU_HOST_MODEL) = range(1000, 1010)
# Flags for check_pool_support
(SUPPORT_STORAGE_CREATEVOLFROM,
SUPPORT_STORAGE_UPLOAD,
SUPPORT_STORAGE_ISACTIVE) = range(2000, 2003)
# Flags for check_nodedev_support
(SUPPORT_NODEDEV_PCI_DETACH,) = range(3000, 3001)
# Flags for check_interface_support
(SUPPORT_INTERFACE_XML_INACTIVE,
SUPPORT_INTERFACE_ISACTIVE) = range(4000, 4002)
# Flags for check_conn_hv_support
(SUPPORT_CONN_HV_VIRTIO,
SUPPORT_CONN_HV_SKIP_DEFAULT_ACPI,
SUPPORT_CONN_HV_SOUND_AC97,
SUPPORT_CONN_HV_SOUND_ICH6,
SUPPORT_CONN_HV_GRAPHICS_SPICE,
SUPPORT_CONN_HV_CHAR_SPICEVMC,
SUPPORT_CONN_HV_DIRECT_INTERFACE,
SUPPORT_CONN_HV_FILESYSTEM) = range(5000, 5008)
# Flags for check_stream_support
(SUPPORT_STREAM_UPLOAD,) = range(6000, 6001)
# Flags for check_net_support
(SUPPORT_NET_ISACTIVE,) = range(7000, 7001)
# Possible keys:
#
# "version" : Minimum libvirt version required for this feature. Not used
# if 'args' provided
#
# "force_version" : Demand that version check is met for the checked
# libvirt version. Normally we will make a best effort
# attempt, because determining the daemon version depends
# on an api call from 2010. So for things like
# testing API availability (e.g. createXMLFrom) we won't
# force the check, but for things like XML options (AC97)
# we want to be ABSOLUTELY SURE it is supported so we
# don't enable it by default and break guest creation.
# This isn't required for versions after >= 0.7.3
#
# "function" : Function name to check exists. If object not specified,
# function is checked against libvirt module.
#
# "args": Argument tuple to actually test object.function with.
#
# "flag": A flag to check exists. This will be appended to the argument
# list if args are provided, otherwise we will only check against
# the local libvirt version.
#
# "drv_version" : A list of tuples of the form
# (driver name (e.g qemu, xen, lxc), minimum supported version)
# If a hypervisor is not listed, it is assumed to be NOT
# SUPPORTED.
#
# "drv_libvirt_version" : List of tuples, similar to drv_version, but
# the version number is minimum supported _libvirt_
# version
# "hv_version" : A list of tuples of the same form as drv_version, however
# listing the actual <domain type='%s'/> from the XML.
# example: 'kvm'
_support_dict = {
SUPPORT_CONN_STORAGE : {
"function" : "virConnect.listStoragePools",
"args" : (),
},
SUPPORT_CONN_NODEDEV : {
"function" : "virConnect.listDevices",
"args" : (None, 0),
},
SUPPORT_CONN_FINDPOOLSOURCES : {
"function" : "virConnect.findStoragePoolSources",
},
SUPPORT_CONN_KEYMAP_AUTODETECT : {
"drv_version" : [("qemu", 11000)],
},
SUPPORT_CONN_GETHOSTNAME : {
"function" : "virConnect.getHostname()",
"args" : (),
},
SUPPORT_CONN_DOMAIN_VIDEO : {
"version" : 6005,
},
SUPPORT_CONN_NETWORK : {
"function" : "virConnect.listNetworks",
"args" : (),
},
SUPPORT_CONN_INTERFACE : {
"function" : "virConnect.listInterfaces",
"args" : (),
},
SUPPORT_CONN_MAXVCPUS_XML : {
"version" : 8005,
},
SUPPORT_CONN_STREAM : {
# Earliest version with working bindings
"version" : 9003,
"function" : "virConnect.newStream",
"args" : (0,),
},
SUPPORT_CONN_GETVERSION : {
"function": "virConnect.getVersion",
"args": (),
},
SUPPORT_CONN_LIBVERSION : {
"function": "virConnect.getLibVersion",
"args": (),
},
SUPPORT_CONN_LISTALLDOMAINS : {
"function": "virConnect.listAllDomains",
"args": (),
},
SUPPORT_CONN_LISTALLNETWORKS : {
"function": "virConnect.listAllNetworks",
"args": (),
},
SUPPORT_CONN_LISTALLSTORAGEPOOLS : {
"function": "virConnect.listAllStoragePools",
"args": (),
},
SUPPORT_CONN_LISTALLINTERFACES : {
"function": "virConnect.listAllInterfaces",
"args": (),
},
#################
# Domain checks #
#################
SUPPORT_DOMAIN_GETVCPUS : {
"function" : "virDomain.vcpus",
"args" : (),
},
SUPPORT_DOMAIN_XML_INACTIVE : {
"function" : "virDomain.XMLDesc",
"args" : (),
"flag" : "VIR_DOMAIN_XML_INACTIVE",
},
SUPPORT_DOMAIN_XML_SECURE : {
"function" : "virDomain.XMLDesc",
"args" : (),
"flag" : "VIR_DOMAIN_XML_SECURE",
},
SUPPORT_DOMAIN_MANAGED_SAVE : {
"function" : "virDomain.hasManagedSaveImage",
"args" : (0,),
},
SUPPORT_DOMAIN_MIGRATE_DOWNTIME : {
"function" : "virDomain.migrateSetMaxDowntime",
# Use a bogus flags value, so that we don't overwrite existing
# downtime value
"args" : (30, 12345678),
},
SUPPORT_DOMAIN_JOB_INFO : {
"function" : "virDomain.jobInfo",
"args" : (),
},
SUPPORT_DOMAIN_CONSOLE_STREAM : {
"version" : 9003,
},
SUPPORT_DOMAIN_SET_METADATA : {
"version" : 9010,
},
SUPPORT_DOMAIN_CPU_HOST_MODEL : {
"version" : 9010,
},
###############
# Pool checks #
###############
# This can't ever require a pool object for back compat reasons
SUPPORT_STORAGE_CREATEVOLFROM : {
"function" : "virStoragePool.createXMLFrom",
"version" : 6004,
},
SUPPORT_STORAGE_ISACTIVE : {
"function" : "virStoragePool.isActive",
"args": (),
},
##################
# Nodedev checks #
##################
# This can't ever require a nodedev object for back compat reasons
SUPPORT_NODEDEV_PCI_DETACH : {
"function" : "virNodeDevice.dettach",
"version" : 6001,
},
####################
# Interface checks #
####################
SUPPORT_INTERFACE_XML_INACTIVE : {
"function" : "virInterface.XMLDesc",
"args" : (),
"flag" : "VIR_INTERFACE_XML_INACTIVE",
},
SUPPORT_INTERFACE_ISACTIVE : {
"function" : "virInterface.isActive",
"args": (),
},
##################
# Conn HV checks #
##################
SUPPORT_CONN_HV_VIRTIO : {
"drv_version": [("qemu", 0)],
"hv_version" : [("kvm", 0)],
},
SUPPORT_CONN_HV_SKIP_DEFAULT_ACPI : {
"drv_version" : [("xen", -3001000)],
},
SUPPORT_CONN_HV_SOUND_AC97 : {
"version" : 6000,
"force_version" : True,
"drv_version" : [("qemu", 11000), ],
},
SUPPORT_CONN_HV_SOUND_ICH6 : {
"version" : 8008,
"drv_version" : [("qemu", 14000), ],
"rhel6_drv_version" : [("qemu", 12001)],
"rhel6_version" : 8007,
},
SUPPORT_CONN_HV_GRAPHICS_SPICE : {
"version" : 8006,
"drv_version" : [("qemu", 14000), ],
},
SUPPORT_CONN_HV_CHAR_SPICEVMC : {
"version" : 8008,
"drv_version" : [("qemu", 14000), ],
},
SUPPORT_CONN_HV_DIRECT_INTERFACE : {
"version" : 8007,
"drv_version" : [("qemu", 0), ],
},
SUPPORT_CONN_HV_FILESYSTEM : {
"drv_version" : [("qemu", 13000),
("lxc", 0),
("openvz", 0),
("test", 0)],
"drv_libvirt_version" : [("qemu", 8005),
("lxc", 0),
("openvz", 0),
("test", 0)],
},
#################
# Stream checks #
#################
SUPPORT_STREAM_UPLOAD : {
# Latest I tested with, and since we will use it by default
# for URL installs, want to be sure it works
"version" : 9004,
},
##################
# Network checks #
##################
SUPPORT_NET_ISACTIVE : {
"function" : "virNetwork.isActive",
"args": (),
},
}
# RHEL6 has lots of feature backports, and since libvirt doesn't # RHEL6 has lots of feature backports, and since libvirt doesn't
# really offer any XML feature introspection, we have to use hacks to # really offer any XML feature introspection, we have to use hacks to
@ -437,6 +101,295 @@ def _split_function_name(function):
return (output[0], output[1]) return (output[0], output[1])
class _SupportCheck(object):
"""
@version: Minimum libvirt version required for this feature. Not used
if 'args' provided
@force_version: Demand that version check is met for the checked
libvirt version. Normally we will make a best effort
attempt, because determining the daemon version depends
on an api call from 2010. So for things like
testing API availability (e.g. createXMLFrom) we won't
force the check, but for things like XML options (AC97)
we want to be ABSOLUTELY SURE it is supported so we
don't enable it by default and break guest creation.
This isn't required for versions after >= 0.7.3
@function: Function name to check exists. If object not specified,
function is checked against libvirt module.
@args: Argument tuple to actually test object.function with.
@flag: A flag to check exists. This will be appended to the argument
list if args are provided, otherwise we will only check against
the local libvirt version.
@drv_version: A list of tuples of the form
(driver name (e.g qemu, xen, lxc), minimum supported version)
If a hypervisor is not listed, it is assumed to be NOT SUPPORTED.
@drv_libvirt_version: List of tuples, similar to drv_version, but
the version number is minimum supported _libvirt_ version
@hv_version: A list of tuples of the same form as drv_version, however
listing the actual <domain type='%s'/> from the XML. example: 'kvm'
@rhel6_version
@rhel6_drv_version: Analog of the above params, but for versions for
RHEL6 qemu, and only if virt-manager is configured with the
rhel defaults switch
"""
def __init__(self,
function=None, args=None, flag=None,
version=None, force_version=None,
drv_version=None, drv_libvirt_version=None, hv_version=None,
rhel6_drv_version=None, rhel6_version=None):
self.function = function
self.args = args
self.flag = flag
self.version = version and int(version) or 0
self.force_version = bool(force_version)
self.drv_version = drv_version or []
self.drv_libvirt_version = drv_libvirt_version or []
self.hv_version = hv_version or []
self.rhel6_version = rhel6_version and int(rhel6_version) or 0
self.rhel6_drv_version = rhel6_drv_version or []
def _get_min_lib_version(self):
ret = self.version
rhel6_min = self.rhel6_version or ret
if get_rhel6():
ret = rhel6_min
return ret
def _get_drv_version(self):
ret = self.drv_version
rhel6_drv_version = self.rhel6_drv_version or ret
if get_rhel6():
ret = rhel6_drv_version
return ret
def check_support(self, conn, data):
minimum_libvirt_version = self._get_min_lib_version()
drv_version = self._get_drv_version()
object_name, function_name = _split_function_name(self.function)
if function_name:
# Make sure function is present in either libvirt module or
# object_name class
flag_tuple = ()
if not _has_command(function_name, objname=object_name):
return False
if self.flag:
found_flag = _get_flag(self.flag)
if not bool(found_flag):
return False
flag_tuple = (found_flag,)
if self.args is not None:
classobj = None
# If function requires an object, make sure the passed obj
# is of the correct type
if object_name:
classobj = _get_command(object_name)
if not isinstance(data, classobj):
raise ValueError(
"Passed obj %s with args must be of type %s, was %s" %
(data, str(classobj), type(data)))
cmd = _get_command(function_name, obj=data)
# Function with args specified is all the proof we need
ret = _try_command(cmd, self.args + flag_tuple,
check_all_error=bool(flag_tuple))
return ret
# Do this after the function check, since there's an ordering issue
# with VirtualConnection
drv_type = conn.get_uri_driver()
actual_lib_ver = conn.local_libvirt_version()
actual_daemon_ver = conn.daemon_version()
actual_drv_ver = conn.conn_version()
if (actual_daemon_ver == 0 and not self.force_version):
# This means the API may not be supported, but we don't care
actual_daemon_ver = 1000000000
# Check that local libvirt version is sufficient
if minimum_libvirt_version > actual_lib_ver:
return False
# Check that daemon version is sufficient
if minimum_libvirt_version > actual_daemon_ver:
return False
# If driver specific version info specified, try to verify
if drv_version:
found = False
for drv, min_drv_ver in drv_version:
if drv != drv_type:
continue
if min_drv_ver < 0:
if actual_drv_ver <= -min_drv_ver:
found = True
break
else:
if actual_drv_ver >= min_drv_ver:
found = True
break
if not found:
return False
if self.drv_libvirt_version:
found = False
for drv, min_lib_ver in self.drv_libvirt_version:
if drv != drv_type:
continue
if min_lib_ver < 0:
if actual_lib_ver <= -min_lib_ver:
found = True
break
else:
if actual_lib_ver >= min_lib_ver:
found = True
break
if not found:
return False
if self.hv_version:
found = False
hv_type = data
for hv, min_hv_ver in self.hv_version:
if hv != hv_type:
continue
# No HV specific version info, just use driver version
if min_hv_ver < 0:
if actual_drv_ver <= -min_hv_ver:
found = True
break
else:
if actual_drv_ver >= min_hv_ver:
found = True
break
if not found:
return False
return True
_support_id = 0
_support_objs = []
def _make(*args, **kwargs):
global _support_id
_support_id += 1
obj = _SupportCheck(*args, **kwargs)
_support_objs.append(obj)
return _support_id
SUPPORT_CONN_STORAGE = _make(function="virConnect.listStoragePools",
args=())
SUPPORT_CONN_NODEDEV = _make(function="virConnect.listDevices", args=(None, 0))
SUPPORT_CONN_FINDPOOLSOURCES = _make(
function="virConnect.findStoragePoolSources")
SUPPORT_CONN_KEYMAP_AUTODETECT = _make(drv_version=[("qemu", 11000)])
SUPPORT_CONN_GETHOSTNAME = _make(function="virConnect.getHostname", args=())
SUPPORT_CONN_DOMAIN_VIDEO = _make(version=6005)
SUPPORT_CONN_NETWORK = _make(function="virConnect.listNetworks", args=())
SUPPORT_CONN_INTERFACE = _make(function="virConnect.listInterfaces", args=())
SUPPORT_CONN_MAXVCPUS_XML = _make(version=8005)
# Earliest version with working bindings
SUPPORT_CONN_STREAM = _make(version=9003,
function="virConnect.newStream",
args=(0,))
SUPPORT_CONN_GETVERSION = _make(function="virConnect.getVersion", args=())
SUPPORT_CONN_LIBVERSION = _make(function="virConnect.getLibVersion", args=())
SUPPORT_CONN_LISTALLDOMAINS = _make(function="virConnect.listAllDomains",
args=())
SUPPORT_CONN_LISTALLNETWORKS = _make(function="virConnect.listAllNetworks",
args=())
SUPPORT_CONN_LISTALLSTORAGEPOOLS = _make(
function="virConnect.listAllStoragePools",
args=())
SUPPORT_CONN_LISTALLINTERFACES = _make(function="virConnect.listAllInterfaces",
args=())
# Domain checks
SUPPORT_DOMAIN_GETVCPUS = _make(function="virDomain.vcpus", args=())
SUPPORT_DOMAIN_XML_INACTIVE = _make(function="virDomain.XMLDesc", args=(),
flag="VIR_DOMAIN_XML_INACTIVE")
SUPPORT_DOMAIN_XML_SECURE = _make(function="virDomain.XMLDesc", args=(),
flag="VIR_DOMAIN_XML_SECURE")
SUPPORT_DOMAIN_MANAGED_SAVE = _make(function="virDomain.hasManagedSaveImage",
args=(0,))
SUPPORT_DOMAIN_MIGRATE_DOWNTIME = _make(
function="virDomain.migrateSetMaxDowntime",
# Use a bogus flags value, so that we don't overwrite existing
# downtime value
args=(30, 12345678))
SUPPORT_DOMAIN_JOB_INFO = _make(function="virDomain.jobInfo", args=())
SUPPORT_DOMAIN_CONSOLE_STREAM = _make(version=9003)
SUPPORT_DOMAIN_SET_METADATA = _make(version=9010)
SUPPORT_DOMAIN_CPU_HOST_MODEL = _make(version=9010)
# Pool checks
# This can't ever require a pool object for back compat reasons
SUPPORT_STORAGE_CREATEVOLFROM = _make(function="virStoragePool.createXMLFrom",
version=6004)
SUPPORT_STORAGE_ISACTIVE = _make(function="virStoragePool.isActive", args=())
# Nodedev checks
# This can't ever require a nodedev object for back compat reasons
SUPPORT_NODEDEV_PCI_DETACH = _make(function="virNodeDevice.dettach",
version=6001)
# Interface checks
SUPPORT_INTERFACE_XML_INACTIVE = _make(function="virInterface.XMLDesc",
flag="VIR_INTERFACE_XML_INACTIVE",
args=())
SUPPORT_INTERFACE_ISACTIVE = _make(function="virInterface.isActive", args=())
# Conn HV checks
SUPPORT_CONN_HV_VIRTIO = _make(drv_version=[("qemu", 0)],
hv_version=[("kvm", 0)])
SUPPORT_CONN_HV_SKIP_DEFAULT_ACPI = _make(drv_version=[("xen", -3001000)])
SUPPORT_CONN_HV_SOUND_AC97 = _make(version=6000,
force_version=True,
drv_version=[("qemu", 11000)])
SUPPORT_CONN_HV_SOUND_ICH6 = _make(version=8008,
drv_version=[("qemu", 14000)],
rhel6_drv_version=[("qemu", 12001)],
rhel6_version=8007)
SUPPORT_CONN_HV_GRAPHICS_SPICE = _make(version=8006,
drv_version=[("qemu", 14000)])
SUPPORT_CONN_HV_CHAR_SPICEVMC = _make(version=8008,
drv_version=[("qemu", 14000)])
SUPPORT_CONN_HV_DIRECT_INTERFACE = _make(version=8007,
drv_version=[("qemu", 0)])
SUPPORT_CONN_HV_FILESYSTEM = _make(
drv_version=[("qemu", 13000), ("lxc", 0), ("openvz", 0), ("test", 0)],
drv_libvirt_version=[("qemu", 8005), ("lxc", 0),
("openvz", 0), ("test", 0)])
# Stream checks
# Latest I tested with, and since we will use it by default
# for URL installs, want to be sure it works
SUPPORT_STREAM_UPLOAD = _make(version=9004)
# Network checks
SUPPORT_NET_ISACTIVE = _make(function="virNetwork.isActive", args=())
def check_support(virtconn, feature, data=None): def check_support(virtconn, feature, data=None):
""" """
Attempt to determine if a specific libvirt feature is support given Attempt to determine if a specific libvirt feature is support given
@ -454,145 +407,5 @@ def check_support(virtconn, feature, data=None):
if "VirtualConnection" in repr(data): if "VirtualConnection" in repr(data):
data = data.libvirtconn data = data.libvirtconn
support_info = _support_dict[feature] sobj = _support_objs[feature - 1]
key_list = support_info.keys() return sobj.check_support(virtconn, data)
def get_value(key):
if key in key_list:
key_list.remove(key)
return support_info.get(key)
is_rhel6 = get_rhel6()
force_version = get_value("force_version") or False
minimum_libvirt_version = get_value("version") or 0
rhel6_min = get_value("rhel6_version") or minimum_libvirt_version
if is_rhel6:
minimum_libvirt_version = rhel6_min
drv_version = get_value("drv_version") or []
rhel6_drv_version = get_value("rhel6_drv_version") or drv_version
if is_rhel6:
drv_version = rhel6_drv_version
drv_libvirt_version = get_value("drv_libvirt_version") or []
hv_version = get_value("hv_version") or []
object_name, function_name = _split_function_name(get_value("function"))
args = get_value("args")
flag = get_value("flag")
# Make sure there are no keys left in the key_list. This will
# ensure we didn't mistype anything above, or in the support_dict
if key_list:
raise RuntimeError("Unknown keys in the support_dict: %s" % key_list)
if function_name:
# Make sure function is present in either libvirt module or
# object_name class
flag_tuple = ()
if not _has_command(function_name, objname=object_name):
return False
if flag:
found_flag = _get_flag(flag)
if not bool(found_flag):
return False
flag_tuple = (found_flag,)
if args is not None:
classobj = None
# If function requires an object, make sure the passed obj
# is of the correct type
if object_name:
classobj = _get_command(object_name)
if not isinstance(data, classobj):
raise ValueError(
"Passed obj %s with args must be of type %s, was %s" %
(data, str(classobj), type(data)))
cmd = _get_command(function_name, obj=data)
# Function with args specified is all the proof we need
ret = _try_command(cmd, args + flag_tuple,
check_all_error=bool(flag_tuple))
return ret
# Do this after the function check, since there's an ordering issue
# with VirtualConnection
drv_type = virtconn.get_uri_driver()
actual_lib_ver = virtconn.local_libvirt_version()
actual_daemon_ver = virtconn.daemon_version()
actual_drv_ver = virtconn.conn_version()
if (actual_daemon_ver == 0 and not force_version):
# This means the API may not be supported, but we don't care
actual_daemon_ver = 1000000000
# Check that local libvirt version is sufficient
if minimum_libvirt_version > actual_lib_ver:
return False
# Check that daemon version is sufficient
if minimum_libvirt_version > actual_daemon_ver:
return False
# If driver specific version info specified, try to verify
if drv_version:
found = False
for drv, min_drv_ver in drv_version:
if drv != drv_type:
continue
if min_drv_ver < 0:
if actual_drv_ver <= -min_drv_ver:
found = True
break
else:
if actual_drv_ver >= min_drv_ver:
found = True
break
if not found:
return False
if drv_libvirt_version:
found = False
for drv, min_lib_ver in drv_libvirt_version:
if drv != drv_type:
continue
if min_lib_ver < 0:
if actual_lib_ver <= -min_lib_ver:
found = True
break
else:
if actual_lib_ver >= min_lib_ver:
found = True
break
if not found:
return False
if hv_version:
found = False
hv_type = data
for hv, min_hv_ver in hv_version:
if hv != hv_type:
continue
# No HV specific version info, just use driver version
if min_hv_ver < 0:
if actual_drv_ver <= -min_hv_ver:
found = True
break
else:
if actual_drv_ver >= min_hv_ver:
found = True
break
if not found:
return False
return True