Coverage for drivers/LUNperVDI.py : 23%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/python3
2#
3# Copyright (C) Citrix Systems Inc.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published
7# by the Free Software Foundation; version 2.1 only.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with this program; if not, write to the Free Software Foundation, Inc.,
16# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17#
18# LUNperVDI: Generic Raw LUN handler, used by HBASR and ISCSISR
19#
21from sm_typing import override
23import os
24import VDI
25import util
26import scsiutil
27import xs_errors
29MAX_TIMEOUT = 15
32class RAWVDI(VDI.VDI):
33 @override
34 def load(self, vdi_uuid) -> None:
35 if not self.sr.attached: 35 ↛ 36line 35 didn't jump to line 36, because the condition on line 35 was never true
36 raise xs_errors.XenError('SRUnavailable')
38 self.uuid = vdi_uuid
39 self.location = vdi_uuid
40 self.managed = False
41 self.vdi_type = "phy"
42 try:
43 vdi_ref = self.sr.session.xenapi.VDI.get_by_uuid(vdi_uuid)
44 self.managed = self.sr.session.xenapi.VDI.get_managed(vdi_ref)
45 self.sm_config = self.sr.session.xenapi.VDI.get_sm_config(vdi_ref)
46 self.path = self.sr.mpathmodule.path(self.sm_config['SCSIid'])
47 except:
48 pass
49 if self.sr.cmd == "vdi_introduce": 49 ↛ 50line 49 didn't jump to line 50, because the condition on line 49 was never true
50 self.managed = True
52 def _query(self, path, id):
53 self.uuid = scsiutil.gen_uuid_from_string(scsiutil.getuniqueserial(path))
54 self.location = self.uuid
55 self.vendor = scsiutil.getmanufacturer(path)
56 self.serial = scsiutil.getserial(path)
57 self.LUNid = id
58 self.size = scsiutil.getsize(path)
59 self.SCSIid = scsiutil.getSCSIid(path)
60 self.path = path
61 sm_config = util.default(self, "sm_config", lambda: {})
62 sm_config['LUNid'] = str(self.LUNid)
63 sm_config['SCSIid'] = self.SCSIid
64 sm_config['backend-kind'] = 'vbd'
65 self.sm_config = sm_config
67 @override
68 def introduce(self, sr_uuid, vdi_uuid) -> str:
69 self.sm_config = self.sr.srcmd.params['vdi_sm_config']
70 vdi_path = self.sr._getLUNbySMconfig(self.sm_config)
71 self._query(vdi_path, self.sm_config['LUNid'])
72 vdi_uuid = self.uuid
73 self.sr.vdis[vdi_uuid] = self
75 try:
76 util._getVDI(self.sr, vdi_uuid)
77 self.sr.vdis[vdi_uuid]._db_update()
78 # For reasons I don't understand, VDI._db_update() doesn't set the
79 # managed flag, so we do that ourselves here.
80 vdi_ref = self.sr.session.xenapi.VDI.get_by_uuid(vdi_uuid)
81 self.sr.session.xenapi.VDI.set_managed(vdi_ref, self.managed)
82 except:
83 self.sr.vdis[vdi_uuid]._db_introduce()
84 return super(RAWVDI, self).get_params()
86 @override
87 def create(self, sr_uuid, vdi_uuid, size) -> str:
88 VDIs = util._getVDIs(self.sr)
89 self.sr._loadvdis()
90 smallest = 0
91 v = {}
92 for vdi in VDIs:
93 if not vdi['managed'] \
94 and int(vdi['virtual_size']) >= int(size) \
95 and vdi['uuid'] in self.sr.vdis:
96 if not smallest:
97 smallest = int(vdi['virtual_size'])
98 v = vdi
99 elif int(vdi['virtual_size']) < smallest:
100 smallest = int(vdi['virtual_size'])
101 v = vdi
102 if smallest > 0:
103 self.managed = True
104 self.sr.session.xenapi.VDI.set_managed(v['vdi_ref'], self.managed)
105 return super(RAWVDI, self.sr.vdis[v['uuid']]).get_params()
106 raise xs_errors.XenError('SRNoSpace')
108 @override
109 def delete(self, sr_uuid, vdi_uuid, data_only=False) -> None:
110 try:
111 vdi = util._getVDI(self.sr, vdi_uuid)
112 if not vdi['managed']:
113 return
114 sm_config = vdi['sm_config']
115 self.sr.session.xenapi.VDI.set_managed(vdi['vdi_ref'], False)
116 except:
117 pass
119 @override
120 def attach(self, sr_uuid, vdi_uuid) -> str:
121 self.sr._loadvdis()
122 if vdi_uuid not in self.sr.vdis:
123 raise xs_errors.XenError('VDIUnavailable')
124 if not util.pathexists(self.path):
125 self.sr.refresh()
126 if 'SCSIid' in self.sm_config:
127 if self.sr.mpath == 'true':
128 self.sr.mpathmodule.refresh(self.sm_config['SCSIid'], 0)
129 devs = os.listdir("/dev/disk/by-scsid/%s" % self.sm_config['SCSIid'])
130 for dev in devs:
131 realdev = os.path.realpath("/dev/disk/by-scsid/%s/%s" % (self.sm_config['SCSIid'], dev))
132 util.set_scheduler(realdev.split("/")[-1])
133 if not util.wait_for_path(self.path, MAX_TIMEOUT):
134 util.SMlog("Unable to detect LUN attached to host [%s]" % self.sr.path)
135 raise xs_errors.XenError('VDIUnavailable')
136 return super(RAWVDI, self).attach(sr_uuid, vdi_uuid)
138 @override
139 def detach(self, sr_uuid, vdi_uuid) -> None:
140 self.sr._loadvdis()
141 if 'SCSIid' in self.sm_config:
142 self.sr.mpathmodule.reset(self.sm_config['SCSIid'], True) # explicitly unmap
143 if vdi_uuid not in self.sr.vdis:
144 raise xs_errors.XenError('VDIUnavailable')
146 def _set_managed(self, vdi_uuid, managed):
147 try:
148 vdi = util._getVDI(self.sr, vdi_uuid)
149 self.sr.session.xenapi.VDI.set_managed(vdi['vdi_ref'], managed)
150 except:
151 raise xs_errors.XenError('VDIUnavailable')