
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
148 lines
5.1 KiB
Python
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)
|