Merge "virt: introduce libosinfo library to set hardware policy"

This commit is contained in:
Jenkins 2016-01-25 22:29:47 +00:00 committed by Gerrit Code Review
commit 26ea5eee77
3 changed files with 171 additions and 0 deletions

View File

@ -2067,3 +2067,8 @@ class RealtimeMaskNotFoundOrInvalid(Invalid):
msg_fmt = _("Realtime policy needs vCPU(s) mask configured with at least "
"1 RT vCPU and 1 ordinary vCPU. See hw:cpu_realtime_mask "
"or hw_cpu_realtime_mask")
class OsInfoNotFound(NotFound):
msg_fmt = _("No configuration information found for operating system "
"%(os_name)s")

View File

@ -0,0 +1,53 @@
# 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.
import mock
from nova import exception
from nova import test
from nova.virt import osinfo
class LibvirtOsInfoTest(test.NoDBTestCase):
def setUp(self):
super(LibvirtOsInfoTest, self).setUp()
osinfo.libosinfo = mock.Mock()
def test_get_os(self):
filter_mock = mock.Mock()
osinfo.libosinfo = mock.Mock()
osinfo.libosinfo.Filter.new.return_value = filter_mock
osinfo_mock = mock.Mock()
filtered_list = osinfo_mock.new_filtered
filtered_list.return_value.get_length.return_value = 1
os_info_db = osinfo._OsInfoDatabase.get_instance()
os_info_db.oslist = osinfo_mock
os_info_db.get_os('test33')
filter_mock.add_constraint.assert_called_once_with('short-id',
'test33')
self.assertTrue(filtered_list.return_value.get_nth.called)
def test_get_os_fails(self):
filter_mock = mock.Mock()
osinfo.libosinfo = mock.Mock()
osinfo.libosinfo.Filter.return_value.new.return_value = filter_mock
osinfo_mock = mock.Mock()
filtered = osinfo_mock.new_filtered.return_value
filtered.get_length.return_value = 0
os_info_db = osinfo._OsInfoDatabase.get_instance()
os_info_db.oslist = osinfo_mock
self.assertRaises(exception.OsInfoNotFound,
os_info_db.get_os,
'test33')

113
nova/virt/osinfo.py Normal file
View File

@ -0,0 +1,113 @@
# 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.i18n import _, _LE
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
if libosinfo is None:
try:
libosinfo = importutils.import_module(
'gi.repository.Libosinfo')
except ImportError as exp:
raise exception.NovaException(
_("Cannot load Libosinfo: (%s)") % exp)
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 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)
filttered = self.oslist.new_filtered(fltr)
list_len = filttered.get_length()
if not list_len:
raise exception.OsInfoNotFound(os_name=os_name)
return filttered.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):
try:
return _OsInfoDatabase.get_instance().get_os(os_name)
except exception.NovaException as e:
LOG.error(_LE("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():
return devs.get_nth(0).get_name()
@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():
return devs.get_nth(0).get_name()