Hide keyboard shortcuts

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 

20 

21import SR 

22import VDI 

23import SRCommand 

24import util 

25import os 

26import time 

27import stat 

28import xs_errors 

29import sysdevice 

30 

31CAPABILITIES = ["VDI_INTRODUCE", "VDI_ATTACH", "VDI_DETACH", "VDI_UPDATE", "SR_UPDATE"] 

32 

33CONFIGURATION = \ 

34 [['location', 'path to mount (required) (e.g. server:/path)']] 

35 

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 } 

46 

47TYPE = 'udev' 

48 

49 

50class udevSR(SR.SR): 

51 """udev-driven storage repository""" 

52 

53 def handles(type): 

54 if type == TYPE: 

55 return True 

56 return False 

57 handles = staticmethod(handles) 

58 

59 def content_type(self, sr_uuid): 

60 return super(udevSR, self).content_type(sr_uuid) 

61 

62 def vdi(self, uuid): 

63 util.SMlog("params = %s" % (self.srcmd.params.keys())) 

64 

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) 

69 

70 return udevVDI(self, vdi_location) 

71 

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) 

76 

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) 

84 

85 def update(self, sr_uuid): 

86 # Return as much information as we have 

87 sr_root = self.dconf['location'] 

88 

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 

94 

95 the_sum = 0 

96 for vdi in self.vdis.values(): 

97 the_sum = the_sum + vdi.size 

98 

99 self.physical_size = the_sum 

100 self.physical_utilisation = the_sum 

101 self.virtual_allocation = the_sum 

102 

103 self._db_update() 

104 

105 def scan(self, sr_uuid): 

106 self.update(sr_uuid) 

107 

108 # base class scan does all the work: 

109 return super(udevSR, self).scan(sr_uuid) 

110 

111 def create(self, sr_uuid, size): 

112 pass 

113 

114 def delete(self, sr_uuid): 

115 pass 

116 

117 def attach(self, sr_uuid): 

118 pass 

119 

120 def detach(self, sr_uuid): 

121 pass 

122 

123 

124def read_whole_file(filename): 

125 f = open(filename, 'r') 

126 try: 

127 return f.readlines() 

128 finally: 

129 f.close() 

130 

131 

132class udevVDI(VDI.VDI): 

133 def __init__(self, sr, location): 

134 self.location = location 

135 VDI.VDI.__init__(self, sr, None) 

136 

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 

146 

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 

150 

151 self.path = os.path.realpath(self.path) 

152 

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 

158 

159 self.label = "%s %s" % (info["bus"], info["bus_path"]) 

160 self.description = info["hwinfo"] 

161 

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" 

165 

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 

175 

176 except OSError as e: 

177 self.deleted = True 

178 

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

186 

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) 

200 

201 def attach(self, sr_uuid, vdi_uuid): 

202 if self.deleted: 

203 raise xs_errors.XenError('VDIUnavailable') 

204 

205 return super(udevVDI, self).attach(sr_uuid, vdi_uuid) 

206 

207 def detach(self, sr_uuid, vdi_uuid): 

208 pass 

209 

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)