Coverage for libs/sm/LUNperVDI.py: 19%

106 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2026-07-10 07:59 +0000

1# 

2# Copyright (C) Citrix Systems Inc. 

3# 

4# This program is free software; you can redistribute it and/or modify 

5# it under the terms of the GNU Lesser General Public License as published 

6# by the Free Software Foundation; version 2.1 only. 

7# 

8# This program is distributed in the hope that it will be useful, 

9# but WITHOUT ANY WARRANTY; without even the implied warranty of 

10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

11# GNU Lesser General Public License for more details. 

12# 

13# You should have received a copy of the GNU Lesser General Public License 

14# along with this program; if not, write to the Free Software Foundation, Inc., 

15# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 

16# 

17# LUNperVDI: Generic Raw LUN handler, used by HBASR and ISCSISR 

18# 

19 

20import os 

21from sm import VDI 

22from sm.core import util 

23from sm.core import scsiutil 

24from sm.core import xs_errors 

25 

26MAX_TIMEOUT = 15 

27 

28 

29class RAWVDI(VDI.VDI): 

30 def load(self, vdi_uuid): 

31 if not self.sr.attached: 31 ↛ 32line 31 didn't jump to line 32, because the condition on line 31 was never true

32 raise xs_errors.XenError('SRUnavailable') 

33 

34 self.uuid = vdi_uuid 

35 self.location = vdi_uuid 

36 self.managed = False 

37 try: 

38 vdi_ref = self.sr.session.xenapi.VDI.get_by_uuid(vdi_uuid) 

39 self.managed = self.sr.session.xenapi.VDI.get_managed(vdi_ref) 

40 self.sm_config = self.sr.session.xenapi.VDI.get_sm_config(vdi_ref) 

41 self.path = self.sr.mpathmodule.path(self.sm_config['SCSIid']) 

42 except: 

43 pass 

44 if self.sr.cmd == "vdi_introduce": 44 ↛ 45line 44 didn't jump to line 45, because the condition on line 44 was never true

45 self.managed = True 

46 

47 def _query(self, path, id): 

48 self.uuid = scsiutil.gen_uuid_from_string(scsiutil.getuniqueserial(path)) 

49 self.location = self.uuid 

50 self.vendor = scsiutil.getmanufacturer(path) 

51 self.serial = scsiutil.getserial(path) 

52 self.LUNid = id 

53 self.size = scsiutil.getsize(path) 

54 self.SCSIid = scsiutil.getSCSIid(path) 

55 self.path = path 

56 sm_config = util.default(self, "sm_config", lambda: {}) 

57 sm_config['LUNid'] = str(self.LUNid) 

58 sm_config['SCSIid'] = self.SCSIid 

59 sm_config['backend-kind'] = 'vbd' 

60 self.sm_config = sm_config 

61 

62 def introduce(self, sr_uuid, vdi_uuid): 

63 self.sm_config = self.sr.srcmd.params['vdi_sm_config'] 

64 vdi_path = self.sr._getLUNbySMconfig(self.sm_config) 

65 self._query(vdi_path, self.sm_config['LUNid']) 

66 vdi_uuid = self.uuid 

67 self.sr.vdis[vdi_uuid] = self 

68 

69 try: 

70 util._getVDI(self.sr, vdi_uuid) 

71 self.sr.vdis[vdi_uuid]._db_update() 

72 # For reasons I don't understand, VDI._db_update() doesn't set the 

73 # managed flag, so we do that ourselves here. 

74 vdi_ref = self.sr.session.xenapi.VDI.get_by_uuid(vdi_uuid) 

75 self.sr.session.xenapi.VDI.set_managed(vdi_ref, self.managed) 

76 except: 

77 self.sr.vdis[vdi_uuid]._db_introduce() 

78 return super(RAWVDI, self).get_params() 

79 

80 def create(self, sr_uuid, vdi_uuid, size): 

81 VDIs = util._getVDIs(self.sr) 

82 self.sr._loadvdis() 

83 smallest = 0 

84 v = None 

85 for vdi in VDIs: 

86 if not vdi['managed'] \ 

87 and int(vdi['virtual_size']) >= int(size) \ 

88 and vdi['uuid'] in self.sr.vdis: 

89 if not smallest: 

90 smallest = int(vdi['virtual_size']) 

91 v = vdi 

92 elif int(vdi['virtual_size']) < smallest: 

93 smallest = int(vdi['virtual_size']) 

94 v = vdi 

95 if smallest > 0: 

96 self.managed = True 

97 self.sr.session.xenapi.VDI.set_managed(v['vdi_ref'], self.managed) 

98 return super(RAWVDI, self.sr.vdis[v['uuid']]).get_params() 

99 raise xs_errors.XenError('SRNoSpace') 

100 

101 def delete(self, sr_uuid, vdi_uuid): 

102 try: 

103 vdi = util._getVDI(self.sr, vdi_uuid) 

104 if not vdi['managed']: 

105 return 

106 sm_config = vdi['sm_config'] 

107 self.sr.session.xenapi.VDI.set_managed(vdi['vdi_ref'], False) 

108 except: 

109 pass 

110 

111 def attach(self, sr_uuid, vdi_uuid): 

112 self.sr._loadvdis() 

113 if vdi_uuid not in self.sr.vdis: 

114 raise xs_errors.XenError('VDIUnavailable') 

115 if not util.pathexists(self.path): 

116 self.sr.refresh() 

117 if 'SCSIid' in self.sm_config: 

118 if self.sr.mpath == 'true': 

119 self.sr.mpathmodule.refresh(self.sm_config['SCSIid'], 0) 

120 devs = os.listdir("/dev/disk/by-scsid/%s" % self.sm_config['SCSIid']) 

121 for dev in devs: 

122 realdev = os.path.realpath("/dev/disk/by-scsid/%s/%s" % (self.sm_config['SCSIid'], dev)) 

123 util.set_scheduler(realdev.split("/")[-1]) 

124 if not util.wait_for_path(self.path, MAX_TIMEOUT): 

125 util.SMlog("Unable to detect LUN attached to host [%s]" % self.sr.path) 

126 raise xs_errors.XenError('VDIUnavailable') 

127 return super(RAWVDI, self).attach(sr_uuid, vdi_uuid) 

128 

129 def detach(self, sr_uuid, vdi_uuid): 

130 self.sr._loadvdis() 

131 if 'SCSIid' in self.sm_config: 

132 self.sr.mpathmodule.reset(self.sm_config['SCSIid'], True) # explicitly unmap 

133 if vdi_uuid not in self.sr.vdis: 

134 raise xs_errors.XenError('VDIUnavailable') 

135 

136 def _set_managed(self, vdi_uuid, managed): 

137 try: 

138 vdi = util._getVDI(self.sr, vdi_uuid) 

139 self.sr.session.xenapi.VDI.set_managed(vdi['vdi_ref'], managed) 

140 except: 

141 raise xs_errors.XenError('VDIUnavailable')