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
« 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#
20import os
21from sm import VDI
22from sm.core import util
23from sm.core import scsiutil
24from sm.core import xs_errors
26MAX_TIMEOUT = 15
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')
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
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
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
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()
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')
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
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)
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')
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')