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,55 +101,74 @@ def _split_function_name(function):
return (output[0], output[1]) return (output[0], output[1])
def check_support(virtconn, feature, data=None): class _SupportCheck(object):
""" """
Attempt to determine if a specific libvirt feature is support given @version: Minimum libvirt version required for this feature. Not used
the passed connection. 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'
@param conn: Libvirt connection to check feature on @rhel6_version
@param feature: Feature type to check support for @rhel6_drv_version: Analog of the above params, but for versions for
@type feature: One of the SUPPORT_* flags RHEL6 qemu, and only if virt-manager is configured with the
@param data: Option libvirt object to use in feature checking rhel defaults switch
@type data: Could be virDomain, virNetwork, virStoragePool,
hv name, etc
@returns: True if feature is supported, False otherwise
""" """
if "VirtualConnection" in repr(data): def __init__(self,
data = data.libvirtconn 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 []
support_info = _support_dict[feature] self.rhel6_version = rhel6_version and int(rhel6_version) or 0
key_list = support_info.keys() self.rhel6_drv_version = rhel6_drv_version or []
def get_value(key): def _get_min_lib_version(self):
if key in key_list: ret = self.version
key_list.remove(key) rhel6_min = self.rhel6_version or ret
return support_info.get(key) if get_rhel6():
ret = rhel6_min
return ret
is_rhel6 = get_rhel6() def _get_drv_version(self):
force_version = get_value("force_version") or False ret = self.drv_version
rhel6_drv_version = self.rhel6_drv_version or ret
if get_rhel6():
ret = rhel6_drv_version
return ret
minimum_libvirt_version = get_value("version") or 0 def check_support(self, conn, data):
rhel6_min = get_value("rhel6_version") or minimum_libvirt_version minimum_libvirt_version = self._get_min_lib_version()
if is_rhel6: drv_version = self._get_drv_version()
minimum_libvirt_version = rhel6_min
drv_version = get_value("drv_version") or [] object_name, function_name = _split_function_name(self.function)
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: if function_name:
# Make sure function is present in either libvirt module or # Make sure function is present in either libvirt module or
@ -495,13 +178,13 @@ def check_support(virtconn, feature, data=None):
if not _has_command(function_name, objname=object_name): if not _has_command(function_name, objname=object_name):
return False return False
if flag: if self.flag:
found_flag = _get_flag(flag) found_flag = _get_flag(self.flag)
if not bool(found_flag): if not bool(found_flag):
return False return False
flag_tuple = (found_flag,) flag_tuple = (found_flag,)
if args is not None: if self.args is not None:
classobj = None classobj = None
# If function requires an object, make sure the passed obj # If function requires an object, make sure the passed obj
@ -516,17 +199,17 @@ def check_support(virtconn, feature, data=None):
cmd = _get_command(function_name, obj=data) cmd = _get_command(function_name, obj=data)
# Function with args specified is all the proof we need # Function with args specified is all the proof we need
ret = _try_command(cmd, args + flag_tuple, ret = _try_command(cmd, self.args + flag_tuple,
check_all_error=bool(flag_tuple)) check_all_error=bool(flag_tuple))
return ret return ret
# Do this after the function check, since there's an ordering issue # Do this after the function check, since there's an ordering issue
# with VirtualConnection # with VirtualConnection
drv_type = virtconn.get_uri_driver() drv_type = conn.get_uri_driver()
actual_lib_ver = virtconn.local_libvirt_version() actual_lib_ver = conn.local_libvirt_version()
actual_daemon_ver = virtconn.daemon_version() actual_daemon_ver = conn.daemon_version()
actual_drv_ver = virtconn.conn_version() actual_drv_ver = conn.conn_version()
if (actual_daemon_ver == 0 and not force_version): if (actual_daemon_ver == 0 and not self.force_version):
# This means the API may not be supported, but we don't care # This means the API may not be supported, but we don't care
actual_daemon_ver = 1000000000 actual_daemon_ver = 1000000000
@ -557,9 +240,9 @@ def check_support(virtconn, feature, data=None):
if not found: if not found:
return False return False
if drv_libvirt_version: if self.drv_libvirt_version:
found = False found = False
for drv, min_lib_ver in drv_libvirt_version: for drv, min_lib_ver in self.drv_libvirt_version:
if drv != drv_type: if drv != drv_type:
continue continue
@ -575,10 +258,10 @@ def check_support(virtconn, feature, data=None):
if not found: if not found:
return False return False
if hv_version: if self.hv_version:
found = False found = False
hv_type = data hv_type = data
for hv, min_hv_ver in hv_version: for hv, min_hv_ver in self.hv_version:
if hv != hv_type: if hv != hv_type:
continue continue
@ -596,3 +279,133 @@ def check_support(virtconn, feature, data=None):
return False return False
return True 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):
"""
Attempt to determine if a specific libvirt feature is support given
the passed connection.
@param conn: Libvirt connection to check feature on
@param feature: Feature type to check support for
@type feature: One of the SUPPORT_* flags
@param data: Option libvirt object to use in feature checking
@type data: Could be virDomain, virNetwork, virStoragePool,
hv name, etc
@returns: True if feature is supported, False otherwise
"""
if "VirtualConnection" in repr(data):
data = data.libvirtconn
sobj = _support_objs[feature - 1]
return sobj.check_support(virtconn, data)