Files
nova/nova/virt/osinfo.py
John Garbutt 6be668e519 Stop sending bad values from libosinfo to libvirt
When we try to use either virtio1.0-block or virtio1.0-net it is
correctly rejected by libvirt. We get these returned from libosinfo for
newer operating systems that support virtio1.0.

As we want to support libvirts older than 5.2.0, its best we just request
"virtio", please see:
https://libvirt.org/formatdomain.html#elementsVirtioTransitional

You can see virtio1.0-net and virtio-block being added here:
https://gitlab.com/libosinfo/osinfo-db/blob/master/data/os/fedoraproject.org/fedora-23.xml.in#L31

Change-Id: I633faae47ad5a33b27f5e2eef6e0107f60335146
Closes-Bug: #1835400
2019-07-04 15:30:51 +01:00

148 lines
5.1 KiB
Python

# Copyright 2015 Red Hat, Inc
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from oslo_utils import importutils
from nova import exception
from nova.objects import fields
libosinfo = None
LOG = logging.getLogger(__name__)
# TODO(vladikr) The current implementation will serve only as a temporary
# solution, due to it's dependency on the libosinfo gobject library.
# In the future it will be replaced by a pure python library or by a direct
# parsing of the libosinfo XML files. However, it will be possible only when
# libosinfo project will declare the XML structure to be a stable ABI.
class _OsInfoDatabase(object):
_instance = None
def __init__(self):
global libosinfo
try:
if libosinfo is None:
libosinfo = importutils.import_module(
'gi.repository.Libosinfo')
except ImportError as exp:
LOG.info("Cannot load Libosinfo: (%s)", exp)
else:
self.loader = libosinfo.Loader()
self.loader.process_default_path()
self.db = self.loader.get_db()
self.oslist = self.db.get_os_list()
@classmethod
def get_instance(cls):
"""Get libosinfo connection
"""
if cls._instance is None:
cls._instance = _OsInfoDatabase()
return cls._instance
def get_os(self, os_name):
"""Retrieve OS object based on id, unique URI identifier of the OS
:param os_name: id - the unique operating systemidentifier
e.g. http://fedoraproject.org/fedora/21,
http://microsoft.com/win/xp,
or a
short-id - the short name of the OS
e.g. fedora21, winxp
:returns: The operation system object Libosinfo.Os
:raise exception.OsInfoNotFound: If os hasn't been found
"""
if libosinfo is None:
return
if not os_name:
raise exception.OsInfoNotFound(os_name='Empty')
fltr = libosinfo.Filter.new()
flt_field = 'id' if os_name.startswith('http') else 'short-id'
fltr.add_constraint(flt_field, os_name)
filtered = self.oslist.new_filtered(fltr)
list_len = filtered.get_length()
if not list_len:
raise exception.OsInfoNotFound(os_name=os_name)
return filtered.get_nth(0)
class OsInfo(object):
"""OS Information Structure
"""
def __init__(self, os_name):
self._os_obj = self._get_os_obj(os_name)
def _get_os_obj(self, os_name):
if os_name is not None:
try:
return _OsInfoDatabase.get_instance().get_os(os_name)
except exception.NovaException as e:
LOG.warning("Cannot find OS information - Reason: (%s)", e)
@property
def network_model(self):
if self._os_obj is not None:
fltr = libosinfo.Filter()
fltr.add_constraint("class", "net")
devs = self._os_obj.get_all_devices(fltr)
if devs.get_length():
net_model = devs.get_nth(0).get_name()
# convert to valid libvirt values
if net_model in ['virtio-net', 'virtio1.0-net']:
return 'virtio'
# ignore any invalid ones
if net_model in fields.VIFModel.ALL:
return net_model
@property
def disk_model(self):
if self._os_obj is not None:
fltr = libosinfo.Filter()
fltr.add_constraint("class", "block")
devs = self._os_obj.get_all_devices(fltr)
if devs.get_length():
disk_model = devs.get_nth(0).get_name()
# convert to valid libvirt values
if disk_model in ['virtio-block', 'virtio1.0-block']:
return 'virtio'
# ignore any invalid ones
if disk_model in fields.DiskBus.ALL:
return disk_model
class HardwareProperties(object):
def __init__(self, image_meta):
""":param image_meta: ImageMeta object
"""
self.img_props = image_meta.properties
os_key = self.img_props.get('os_distro')
self.os_info_obj = OsInfo(os_key)
@property
def network_model(self):
return self.img_props.get('hw_vif_model',
self.os_info_obj.network_model)
@property
def disk_model(self):
return self.img_props.get('hw_disk_bus',
self.os_info_obj.disk_model)