Coverage for drivers/udevSR.py : 36%

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# udevSR: represents VDIs which are hotplugged into dom0 via udev e.g.
19# USB CDROM/disk devices
21import SR
22import VDI
23import SRCommand
24import util
25import os
26import time
27import stat
28import xs_errors
29import sysdevice
31CAPABILITIES = ["VDI_INTRODUCE", "VDI_ATTACH", "VDI_DETACH", "VDI_UPDATE", "SR_UPDATE"]
33CONFIGURATION = \
34 [['location', 'path to mount (required) (e.g. server:/path)']]
36DRIVER_INFO = {
37 'name': 'udev',
38 'description': 'SR plugin which represents devices plugged in via udev as VDIs',
39 'vendor': 'Citrix Systems Inc',
40 'copyright': '(C) 2008 Citrix Systems Inc',
41 'driver_version': '1.0',
42 'required_api_version': '1.1',
43 'capabilities': CAPABILITIES,
44 'configuration': CONFIGURATION
45 }
47TYPE = 'udev'
50class udevSR(SR.SR):
51 """udev-driven storage repository"""
53 def handles(type):
54 if type == TYPE:
55 return True
56 return False
57 handles = staticmethod(handles)
59 def content_type(self, sr_uuid):
60 return super(udevSR, self).content_type(sr_uuid)
62 def vdi(self, uuid):
63 util.SMlog("params = %s" % (self.srcmd.params.keys()))
65 if 'vdi_location' in self.srcmd.params: 65 ↛ 66line 65 didn't jump to line 66, because the condition on line 65 was never true
66 vdi_location = self.srcmd.params['vdi_location']
67 else:
68 vdi_location = self.get_vdi_location(uuid)
70 return udevVDI(self, vdi_location)
72 def get_vdi_location(self, uuid):
73 vdi = self.session.xenapi.VDI
74 vdi_ref = vdi.get_by_uuid(uuid)
75 return vdi.get_location(vdi_ref)
77 def load(self, sr_uuid):
78 # First of all, check we've got the correct keys in dconf
79 if 'location' not in self.dconf:
80 raise xs_errors.XenError('ConfigLocationMissing')
81 self.sr_vditype = 'phy'
82 # Cache the sm_config
83 self.sm_config = self.session.xenapi.SR.get_sm_config(self.sr_ref)
85 def update(self, sr_uuid):
86 # Return as much information as we have
87 sr_root = self.dconf['location']
89 if util.pathexists(sr_root):
90 for filename in os.listdir(sr_root):
91 path = os.path.join(sr_root, filename)
92 x = udevVDI(self, path)
93 self.vdis[path] = x
95 the_sum = 0
96 for vdi in self.vdis.values():
97 the_sum = the_sum + vdi.size
99 self.physical_size = the_sum
100 self.physical_utilisation = the_sum
101 self.virtual_allocation = the_sum
103 self._db_update()
105 def scan(self, sr_uuid):
106 self.update(sr_uuid)
108 # base class scan does all the work:
109 return super(udevSR, self).scan(sr_uuid)
111 def create(self, sr_uuid, size):
112 pass
114 def delete(self, sr_uuid):
115 pass
117 def attach(self, sr_uuid):
118 pass
120 def detach(self, sr_uuid):
121 pass
124def read_whole_file(filename):
125 f = open(filename, 'r')
126 try:
127 return f.readlines()
128 finally:
129 f.close()
132class udevVDI(VDI.VDI):
133 def __init__(self, sr, location):
134 self.location = location
135 VDI.VDI.__init__(self, sr, None)
137 def load(self, location):
138 self.path = self.location
139 self.size = 0
140 self.utilisation = 0
141 self.label = self.path
142 self.sm_config = {}
143 try:
144 s = os.stat(self.path)
145 self.deleted = False
147 # Use the CTIME of the symlink to mean "time it was hotplugged"
148 iso8601 = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(s[stat.ST_CTIME]))
149 self.sm_config['hotplugged_at'] = iso8601
151 self.path = os.path.realpath(self.path)
153 dev = os.path.basename(self.path)
154 info = sysdevice.stat(dev)
155 if "size" in info.keys():
156 self.size = info["size"]
157 self.utilisation = self.size
159 self.label = "%s %s" % (info["bus"], info["bus_path"])
160 self.description = info["hwinfo"]
162 # XXX: what other information can we recover?
163 if 'type' in self.sr.sm_config:
164 self.read_only = self.sr.sm_config['type'] == "cd"
166 usb_path = info.get("usb_path")
167 if usb_path:
168 self.sm_config["usb_path"] = info["usb_path"]
169 pusbs = self.session.xenapi.PUSB.get_all_records()
170 for pusb in pusbs.values():
171 if usb_path == pusb.get("path"):
172 if pusb.get("passthrough_enabled"):
173 raise xs_errors.XenError('VDIUnavailable')
174 break
176 except OSError as e:
177 self.deleted = True
179 def introduce(self, sr_uuid, vdi_uuid):
180 self.uuid = vdi_uuid
181 self.location = self.sr.srcmd.params['vdi_location']
182 self._db_introduce()
183 # Update the physical_utilisation etc
184 self.sr.update(sr_uuid)
185 return super(udevVDI, self).get_params()
187 def update(self, sr_uuid, vdi_location):
188 self.load(vdi_location)
189 # _db_update requires self.uuid to be set
190 self.uuid = self.sr.srcmd.params['vdi_uuid']
191 self._db_update()
192 # also reset the name-label and description since we're a bit of
193 # a special SR
194 # this would lead to an infinite loop as VDI.set_name_label now
195 # calls VDI.update
196 # temporarily commenting this to pass quicktest
197 #vdi = self.sr.session.xenapi.VDI.get_by_uuid(self.uuid)
198 #self.sr.session.xenapi.VDI.set_name_label(vdi, self.label)
199 #self.sr.session.xenapi.VDI.set_name_description(vdi, self.description)
201 def attach(self, sr_uuid, vdi_uuid):
202 if self.deleted:
203 raise xs_errors.XenError('VDIUnavailable')
205 return super(udevVDI, self).attach(sr_uuid, vdi_uuid)
207 def detach(self, sr_uuid, vdi_uuid):
208 pass
210if __name__ == '__main__': 210 ↛ 211line 210 didn't jump to line 211, because the condition on line 210 was never true
211 SRCommand.run(udevSR, DRIVER_INFO)
212else:
213 SR.registerSR(udevSR)