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

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. 

14 

15from oslo_log import log as logging 

16from oslo_utils import importutils 

17 

18from nova import exception 

19from nova.objects import fields 

20 

21libosinfo = None 

22LOG = logging.getLogger(__name__) 

23 

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. 

29 

30 

31class _OsInfoDatabase(object): 

32 

33 _instance = None 

34 

35 def __init__(self): 

36 

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() 

47 

48 self.db = self.loader.get_db() 

49 self.oslist = self.db.get_os_list() 

50 

51 @classmethod 

52 def get_instance(cls): 

53 """Get libosinfo connection 

54 """ 

55 if cls._instance is None: 

56 cls._instance = _OsInfoDatabase() 

57 

58 return cls._instance 

59 

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) 

83 

84 

85class OsInfo(object): 

86 """OS Information Structure 

87 """ 

88 

89 def __init__(self, os_name): 

90 self._os_obj = self._get_os_obj(os_name) 

91 

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) 

98 

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 

113 

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 

128 

129 

130class HardwareProperties(object): 

131 

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) 

138 

139 @property 

140 def network_model(self): 

141 return self.img_props.get('hw_vif_model', 

142 self.os_info_obj.network_model) 

143 

144 @property 

145 def disk_model(self): 

146 return self.img_props.get('hw_disk_bus', 

147 self.os_info_obj.disk_model)