Coverage for nova/virt/osinfo.py: 94%
80 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-24 11:16 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-04-24 11:16 +0000
1# Copyright 2015 Red Hat, Inc
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
15from oslo_log import log as logging
16from oslo_utils import importutils
18from nova import exception
19from nova.objects import fields
21libosinfo = None
22LOG = logging.getLogger(__name__)
24# TODO(vladikr) The current implementation will serve only as a temporary
25# solution, due to it's dependency on the libosinfo gobject library.
26# In the future it will be replaced by a pure python library or by a direct
27# parsing of the libosinfo XML files. However, it will be possible only when
28# libosinfo project will declare the XML structure to be a stable ABI.
31class _OsInfoDatabase(object):
33 _instance = None
35 def __init__(self):
37 global libosinfo
38 try:
39 if libosinfo is None:
40 libosinfo = importutils.import_module(
41 'gi.repository.Libosinfo')
42 except ImportError as exp:
43 LOG.info("Cannot load Libosinfo: (%s)", exp)
44 else:
45 self.loader = libosinfo.Loader()
46 self.loader.process_default_path()
48 self.db = self.loader.get_db()
49 self.oslist = self.db.get_os_list()
51 @classmethod
52 def get_instance(cls):
53 """Get libosinfo connection
54 """
55 if cls._instance is None:
56 cls._instance = _OsInfoDatabase()
58 return cls._instance
60 def get_os(self, os_name):
61 """Retrieve OS object based on id, unique URI identifier of the OS
62 :param os_name: id - the unique operating systemidentifier
63 e.g. http://fedoraproject.org/fedora/21,
64 http://microsoft.com/win/xp,
65 or a
66 short-id - the short name of the OS
67 e.g. fedora21, winxp
68 :returns: The operation system object Libosinfo.Os
69 :raise exception.OsInfoNotFound: If os hasn't been found
70 """
71 if libosinfo is None:
72 return
73 if not os_name: 73 ↛ 74line 73 didn't jump to line 74 because the condition on line 73 was never true
74 raise exception.OsInfoNotFound(os_name='Empty')
75 fltr = libosinfo.Filter.new()
76 flt_field = 'id' if os_name.startswith('http') else 'short-id'
77 fltr.add_constraint(flt_field, os_name)
78 filtered = self.oslist.new_filtered(fltr)
79 list_len = filtered.get_length()
80 if not list_len:
81 raise exception.OsInfoNotFound(os_name=os_name)
82 return filtered.get_nth(0)
85class OsInfo(object):
86 """OS Information Structure
87 """
89 def __init__(self, os_name):
90 self._os_obj = self._get_os_obj(os_name)
92 def _get_os_obj(self, os_name):
93 if os_name is not None:
94 try:
95 return _OsInfoDatabase.get_instance().get_os(os_name)
96 except exception.NovaException as e:
97 LOG.warning("Cannot find OS information - Reason: (%s)", e)
99 @property
100 def network_model(self):
101 if self._os_obj is not None:
102 fltr = libosinfo.Filter()
103 fltr.add_constraint("class", "net")
104 devs = self._os_obj.get_all_devices(fltr)
105 if devs.get_length(): 105 ↛ exitline 105 didn't return from function 'network_model' because the condition on line 105 was always true
106 net_model = devs.get_nth(0).get_name()
107 # convert to valid libvirt values
108 if net_model in ['virtio-net', 'virtio1.0-net']:
109 return 'virtio'
110 # ignore any invalid ones
111 if net_model in fields.VIFModel.ALL:
112 return net_model
114 @property
115 def disk_model(self):
116 if self._os_obj is not None:
117 fltr = libosinfo.Filter()
118 fltr.add_constraint("class", "block")
119 devs = self._os_obj.get_all_devices(fltr)
120 if devs.get_length(): 120 ↛ exitline 120 didn't return from function 'disk_model' because the condition on line 120 was always true
121 disk_model = devs.get_nth(0).get_name()
122 # convert to valid libvirt values
123 if disk_model in ['virtio-block', 'virtio1.0-block']:
124 return 'virtio'
125 # ignore any invalid ones
126 if disk_model in fields.DiskBus.ALL:
127 return disk_model
130class HardwareProperties(object):
132 def __init__(self, image_meta):
133 """:param image_meta: ImageMeta object
134 """
135 self.img_props = image_meta.properties
136 os_key = self.img_props.get('os_distro')
137 self.os_info_obj = OsInfo(os_key)
139 @property
140 def network_model(self):
141 return self.img_props.get('hw_vif_model',
142 self.os_info_obj.network_model)
144 @property
145 def disk_model(self):
146 return self.img_props.get('hw_disk_bus',
147 self.os_info_obj.disk_model)