2013-03-18 01:06:52 +04:00
#
2013-10-28 00:59:46 +04:00
# Copyright 2010, 2013 Red Hat, Inc.
2013-03-18 01:06:52 +04:00
# Cole Robinson <crobinso@redhat.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
2013-10-28 00:59:47 +04:00
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
2013-03-18 01:06:52 +04:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA.
2016-06-15 01:19:09 +03:00
from . domainnumatune import DomainNumatune
2014-09-12 23:59:22 +04:00
from . xmlbuilder import XMLBuilder , XMLProperty , XMLChildProperty
2013-03-18 01:06:52 +04:00
2013-04-13 22:34:52 +04:00
2016-06-15 01:19:09 +03:00
class _CPUCell ( XMLBuilder ) :
"""
Class for generating < cpu > < numa > child < cell > XML
"""
_XML_ROOT_NAME = " cell "
_XML_PROP_ORDER = [ " id " , " cpus " , " memory " ]
def _validate_cpuset ( self , val ) :
DomainNumatune . validate_cpuset ( self . conn , val )
id = XMLProperty ( " ./@id " , is_int = True )
cpus = XMLProperty ( " ./@cpus " , validate_cb = _validate_cpuset )
memory = XMLProperty ( " ./@memory " , is_int = True )
2013-07-14 02:56:09 +04:00
class CPUFeature ( XMLBuilder ) :
2013-03-18 01:06:52 +04:00
"""
Class for generating < cpu > child < feature > XML
"""
POLICIES = [ " force " , " require " , " optional " , " disable " , " forbid " ]
2013-09-11 19:47:09 +04:00
_XML_ROOT_NAME = " feature "
2014-01-31 22:44:50 +04:00
_XML_PROP_ORDER = [ " policy " , " name " ]
2013-03-18 01:06:52 +04:00
2013-09-11 02:32:10 +04:00
name = XMLProperty ( " ./@name " )
policy = XMLProperty ( " ./@policy " )
2013-03-18 01:06:52 +04:00
2013-07-14 02:56:09 +04:00
class CPU ( XMLBuilder ) :
2013-03-18 01:06:52 +04:00
"""
Class for generating < cpu > XML
"""
MATCHS = [ " minimum " , " exact " , " strict " ]
2013-09-11 19:47:09 +04:00
_XML_ROOT_NAME = " cpu "
2013-07-18 01:11:18 +04:00
_XML_PROP_ORDER = [ " mode " , " match " , " model " , " vendor " ,
2013-09-11 02:32:10 +04:00
" sockets " , " cores " , " threads " , " features " ]
2013-03-18 01:06:52 +04:00
2014-02-05 22:51:53 +04:00
special_mode_was_set = False
# These values are exposed on the command line, so are stable API
SPECIAL_MODE_HOST_MODEL_ONLY = " host-model-only "
SPECIAL_MODE_HV_DEFAULT = " hv-default "
SPECIAL_MODE_HOST_COPY = " host-copy "
SPECIAL_MODE_HOST_MODEL = " host-model "
SPECIAL_MODE_HOST_PASSTHROUGH = " host-passthrough "
SPECIAL_MODE_CLEAR = " clear "
SPECIAL_MODES = [ SPECIAL_MODE_HOST_MODEL_ONLY , SPECIAL_MODE_HV_DEFAULT ,
SPECIAL_MODE_HOST_COPY , SPECIAL_MODE_HOST_MODEL ,
SPECIAL_MODE_HOST_PASSTHROUGH , SPECIAL_MODE_CLEAR ]
def set_special_mode ( self , val ) :
if ( val == self . SPECIAL_MODE_HOST_MODEL or
val == self . SPECIAL_MODE_HOST_PASSTHROUGH ) :
self . model = None
2015-03-27 00:08:15 +03:00
self . vendor = None
self . model_fallback = None
for f in self . features :
self . remove_feature ( f )
2014-02-05 22:51:53 +04:00
self . mode = val
elif val == self . SPECIAL_MODE_HOST_COPY :
self . copy_host_cpu ( )
elif ( val == self . SPECIAL_MODE_HV_DEFAULT or
val == self . SPECIAL_MODE_CLEAR ) :
self . clear ( )
elif val == self . SPECIAL_MODE_HOST_MODEL_ONLY :
if self . conn . caps . host . cpu . model :
self . model = self . conn . caps . host . cpu . model
else :
raise RuntimeError ( " programming error: unknown "
" special cpu mode ' %s ' " % val )
self . special_mode_was_set = True
2013-03-18 01:06:52 +04:00
def add_feature ( self , name , policy = " require " ) :
2013-09-11 02:32:10 +04:00
feature = CPUFeature ( self . conn )
feature . name = name
2013-03-18 01:06:52 +04:00
feature . policy = policy
2015-09-04 22:45:45 +03:00
self . add_child ( feature )
2013-03-18 01:06:52 +04:00
def remove_feature ( self , feature ) :
2015-09-04 22:45:45 +03:00
self . remove_child ( feature )
2013-09-11 02:32:10 +04:00
features = XMLChildProperty ( CPUFeature )
2013-03-18 01:06:52 +04:00
2016-06-15 01:19:09 +03:00
cells = XMLChildProperty ( _CPUCell , relative_xpath = " ./numa " )
def add_cell ( self ) :
obj = _CPUCell ( self . conn )
self . add_child ( obj )
return obj
2013-03-18 01:06:52 +04:00
def copy_host_cpu ( self ) :
"""
Enact the equivalent of qemu - cpu host , pulling all info
from capabilities about the host CPU
"""
2013-07-06 22:12:13 +04:00
cpu = self . conn . caps . host . cpu
2013-03-18 01:06:52 +04:00
if not cpu . model :
raise ValueError ( _ ( " No host CPU reported in capabilities " ) )
2013-04-11 09:45:45 +04:00
self . mode = " custom "
2013-03-18 01:06:52 +04:00
self . match = " exact "
self . model = cpu . model
self . vendor = cpu . vendor
for feature in self . features :
self . remove_feature ( feature )
2015-07-14 16:53:25 +03:00
for feature in cpu . features :
self . add_feature ( feature . name )
2013-03-18 01:06:52 +04:00
def vcpus_from_topology ( self ) :
"""
Determine the CPU count represented by topology , or 1 if
no topology is set
"""
self . set_topology_defaults ( )
if self . sockets :
return self . sockets * self . cores * self . threads
return 1
def set_topology_defaults ( self , vcpus = None ) :
"""
Fill in unset topology values , using the passed vcpus count if
required
"""
if ( self . sockets is None and
self . cores is None and
self . threads is None ) :
return
if vcpus is None :
if self . sockets is None :
self . sockets = 1
if self . threads is None :
self . threads = 1
if self . cores is None :
self . cores = 1
vcpus = int ( vcpus or 0 )
if not self . sockets :
if not self . cores :
self . sockets = vcpus / self . threads
else :
self . sockets = vcpus / self . cores
if not self . cores :
if not self . threads :
self . cores = vcpus / self . sockets
else :
self . cores = vcpus / ( self . sockets * self . threads )
if not self . threads :
self . threads = vcpus / ( self . sockets * self . cores )
return
2013-07-18 01:11:18 +04:00
##################
# XML properties #
##################
def _set_model ( self , val ) :
if val :
2013-04-11 09:45:45 +04:00
self . mode = " custom "
2013-07-18 01:11:18 +04:00
if not self . match :
self . match = " exact "
return val
2013-09-19 21:27:30 +04:00
model = XMLProperty ( " ./model " , set_converter = _set_model )
2015-03-27 00:08:15 +03:00
model_fallback = XMLProperty ( " ./model/@fallback " )
2013-07-18 01:11:18 +04:00
2013-09-19 21:27:30 +04:00
match = XMLProperty ( " ./@match " )
vendor = XMLProperty ( " ./vendor " )
mode = XMLProperty ( " ./@mode " )
2013-07-18 01:11:18 +04:00
2013-09-19 21:27:30 +04:00
sockets = XMLProperty ( " ./topology/@sockets " , is_int = True )
cores = XMLProperty ( " ./topology/@cores " , is_int = True )
threads = XMLProperty ( " ./topology/@threads " , is_int = True )