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# DummySR: an example dummy SR for the SDK 

19 

20from sm_typing import Dict, Optional, List, Tuple, override 

21 

22import SR 

23import VDI 

24import SRCommand 

25import util 

26import time 

27import xs_errors 

28 

29CAPABILITIES = ["SR_PROBE", "VDI_CREATE", "VDI_DELETE", "VDI_ATTACH", "VDI_DETACH", 

30 "VDI_ACTIVATE", "VDI_DEACTIVATE", "VDI_CLONE", "VDI_SNAPSHOT", "VDI_RESIZE", 

31 "VDI_INTRODUCE", "VDI_MIRROR"] 

32 

33CONFIGURATION: List[Tuple[str, str]] = [] 

34 

35DRIVER_INFO = { 

36 'name': 'dummy', 

37 'description': 'SR plugin which manages fake data', 

38 'vendor': 'Citrix Systems Inc', 

39 'copyright': '(C) 2008 Citrix Systems Inc', 

40 'driver_version': '1.0', 

41 'required_api_version': '1.1', 

42 'capabilities': CAPABILITIES, 

43 'configuration': CONFIGURATION 

44 } 

45 

46TYPE = 'dummy' 

47 

48 

49class DummySR(SR.SR): 

50 """dummy storage repository""" 

51 

52 @override 

53 @staticmethod 

54 def handles(type) -> bool: 

55 if type == TYPE: 

56 return True 

57 return False 

58 

59 @override 

60 def load(self, sr_uuid) -> None: 

61 self.sr_vditype = 'phy' 

62 

63 @override 

64 def content_type(self, sr_uuid) -> str: 

65 return super(DummySR, self).content_type(sr_uuid) 

66 

67 @override 

68 def create(self, sr_uuid, size) -> None: 

69 self._assertValues(['sr_uuid', 'args', 'host_ref', 'session_ref', 'device_config', 'command', 'sr_ref']) 

70 assert(len(self.srcmd.params['args']) == 1) 

71 

72 @override 

73 def delete(self, sr_uuid) -> None: 

74 self._assertValues(['sr_uuid', 'args', 'host_ref', 'session_ref', 'device_config', 'command', 'sr_ref']) 

75 assert(len(self.srcmd.params['args']) == 0) 

76 

77 @override 

78 def attach(self, sr_uuid) -> None: 

79 self._assertValues(['sr_uuid', 'args', 'host_ref', 'session_ref', 'device_config', 'command', 'sr_ref']) 

80 assert(len(self.srcmd.params['args']) == 0) 

81 

82 @override 

83 def detach(self, sr_uuid) -> None: 

84 self._assertValues(['sr_uuid', 'args', 'host_ref', 'session_ref', 'device_config', 'command', 'sr_ref']) 

85 assert(len(self.srcmd.params['args']) == 0) 

86 

87 @override 

88 def probe(self) -> str: 

89 # N.B. There are no SR references 

90 self._assertValues(['args', 'host_ref', 'session_ref', 'device_config', 'command']) 

91 assert(len(self.srcmd.params['args']) == 0) 

92 

93 # Create some Dummy SR records 

94 entry = {} 

95 entry['size'] = 1024 

96 SRlist = {} 

97 SRlist[util.gen_uuid()] = entry 

98 

99 # Return the Probe XML 

100 return util.SRtoXML(SRlist) 

101 

102 @override 

103 def vdi(self, uuid) -> VDI.VDI: 

104 return DummyVDI(self, uuid) 

105 

106 @override 

107 def scan(self, sr_uuid) -> None: 

108 self._assertValues(['sr_uuid', 'args', 'host_ref', 'session_ref', 'device_config', 'command', 'sr_ref']) 

109 assert(len(self.srcmd.params['args']) == 0) 

110 

111 # The list of VDIs comes from the XenAPI - we have no state 

112 for v in self._getallVDIrecords(): 

113 x = DummyVDI(self, v['uuid']) 

114 x.size = v['virtual_size'] 

115 x.utilisation = v['physical_utilisation'] 

116 self.vdis[x.uuid] = x 

117 

118 self.physical_size = 2000000000000 

119 self.physical_utilisation = 0 

120 self.virtual_allocation = 0 

121 super(DummySR, self).scan(sr_uuid) 

122 

123 def _assertValues(self, vals): 

124 for attr in vals: 

125 assert(attr in self.srcmd.params) 

126 util.SMlog("%s param %s: [%s]" % (self.cmd, attr, self.srcmd.params[attr])) 

127 

128 # Iterate through the device_config dictionary 

129 for key in self.dconf.keys(): 

130 util.SMlog("\tdevice_config: [%s:%s]" % (key, self.dconf[key])) 

131 

132 # Query the sm_config; parameters can be set at Create time. Iterate through keys 

133 self.sm_config = self.session.xenapi.SR.get_sm_config(self.sr_ref) 

134 for key in self.sm_config.keys(): 

135 util.SMlog("\tsm_config: [%s:%s]" % (key, self.sm_config[key])) 

136 

137 def _getallVDIrecords(self): 

138 """Helper function which returns a list of all VDI records for this SR 

139 stored in the XenAPI server""" 

140 # Returns a list of (reference, record) pairs: we only need the records 

141 vdis = list(self.session.VDI.get_all_records(self.session_ref)['Value'].values()) 

142 # We only need the VDIs corresponding to this SR 

143 return [v for v in vdis if v['SR'] == self.sr_ref] 

144 

145 

146class DummyVDI(VDI.VDI): 

147 @override 

148 def load(self, vdi_uuid) -> None: 

149 self.path = "/dev/null" # returned on attach 

150 self.uuid = vdi_uuid 

151 self.size = 0 

152 self.utilisation = 0 

153 self.location = vdi_uuid 

154 self.sm_config: Dict[str, str] = {} 

155 

156 @override 

157 def create(self, sr_uuid, vdi_uuid, size) -> str: 

158 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref', 'vdi_sm_config']) 

159 assert(len(self.sr.srcmd.params['args']) == 8) 

160 

161 self.vdi_sm_config = self.sr.srcmd.params['vdi_sm_config'] 

162 for key in self.vdi_sm_config.keys(): 

163 util.SMlog("\tvdi_sm_config: [%s:%s]" % (key, self.vdi_sm_config[key])) 

164 

165 for v in self.sr._getallVDIrecords(): 

166 if v['uuid'] == vdi_uuid: 

167 raise xs_errors.XenError('VDIExists') 

168 

169 self.size = size 

170 self.utilisation = size 

171 self.sm_config['samplekey'] = "This is a dummy SR VDI" 

172 self._db_introduce() 

173 self.run_corner_cases_tests() 

174 return self.get_params() 

175 

176 @override 

177 def delete(self, sr_uuid, vdi_uuid, data_only=False) -> None: 

178 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref', 'vdi_ref', 'vdi_location', 'vdi_uuid']) 

179 assert(len(self.sr.srcmd.params['args']) == 0) 

180 

181 # Assert that the VDI record exists 

182 self.session.VDI.get_record(self.sr.session_ref) 

183 self.run_corner_cases_tests() 

184 self._db_forget() 

185 

186 @override 

187 def introduce(self, sr_uuid, vdi_uuid) -> str: 

188 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref', 'vdi_sm_config', 'new_uuid']) 

189 assert(len(self.sr.srcmd.params['args']) == 0) 

190 self.vdi_sm_config = self.sr.srcmd.params['vdi_sm_config'] 

191 for key in self.vdi_sm_config.keys(): 

192 util.SMlog("\tvdi_sm_config: [%s:%s]" % (key, self.vdi_sm_config[key])) 

193 

194 for v in self.sr._getallVDIrecords(): 

195 if v['uuid'] == vdi_uuid: 

196 raise xs_errors.XenError('VDIExists') 

197 self.uuid = vdi_uuid 

198 self.location = self.sr.srcmd.params['vdi_location'] 

199 self._db_introduce() 

200 self.run_corner_cases_tests() 

201 return super(DummyVDI, self).get_params() 

202 

203 @override 

204 def attach(self, sr_uuid, vdi_uuid) -> str: 

205 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref', 'vdi_ref', 'vdi_location', 'vdi_uuid']) 

206 assert(len(self.sr.srcmd.params['args']) == 1) 

207 vdi = super(DummyVDI, self).attach(sr_uuid, vdi_uuid) 

208 self.run_corner_cases_tests() 

209 return vdi 

210 

211 @override 

212 def detach(self, sr_uuid, vdi_uuid) -> None: 

213 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref', 'vdi_ref', 'vdi_location', 'vdi_uuid']) 

214 self.run_corner_cases_tests() 

215 assert(len(self.sr.srcmd.params['args']) == 0) 

216 

217 @override 

218 def activate(self, sr_uuid, vdi_uuid) -> Optional[Dict[str, str]]: 

219 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref', 'vdi_ref', 'vdi_location', 'vdi_uuid']) 

220 assert(len(self.sr.srcmd.params['args']) == 1) 

221 self.vdi_ref = self.sr.srcmd.params['vdi_ref'] 

222 self.other_config = self.session.xenapi.VDI.get_other_config(self.vdi_ref) 

223 self.run_corner_cases_tests() 

224 for key in self.other_config.keys(): 

225 util.SMlog("\tvdi_other_config: [%s:%s]" % (key, self.other_config[key])) 

226 return None 

227 

228 @override 

229 def deactivate(self, sr_uuid, vdi_uuid) -> None: 

230 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref', 'vdi_ref', 'vdi_location', 'vdi_uuid']) 

231 self.run_corner_cases_tests() 

232 assert(len(self.sr.srcmd.params['args']) == 0) 

233 

234 @override 

235 def resize(self, sr_uuid, vdi_uuid, size) -> str: 

236 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref', 'vdi_ref', 'vdi_location', 'vdi_uuid']) 

237 assert(len(self.sr.srcmd.params['args']) == 1) 

238 

239 self.size = size 

240 self.utilisation = size 

241 self._db_update() 

242 self.run_corner_cases_tests() 

243 return super(DummyVDI, self).get_params() 

244 

245 @override 

246 def snapshot(self, sr_uuid, vdi_uuid) -> str: 

247 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref']) 

248 assert(len(self.sr.srcmd.params['args']) == 0) 

249 

250 dest = util.gen_uuid() 

251 vdi = VDI.VDI(self.sr, dest) 

252 vdi.read_only = True 

253 vdi.location = dest 

254 vdi.size = 0 

255 vdi.utilisation = 0 

256 vdi._db_introduce() 

257 self.run_corner_cases_tests() 

258 return vdi.get_params() 

259 

260 @override 

261 def clone(self, sr_uuid, vdi_uuid) -> str: 

262 self.sr._assertValues(['sr_uuid', 'args', 'host_ref', 'device_config', 'command', 'sr_ref']) 

263 assert(len(self.sr.srcmd.params['args']) == 0) 

264 

265 dest = util.gen_uuid() 

266 vdi = VDI.VDI(self.sr, dest) 

267 vdi.read_only = False 

268 vdi.location = dest 

269 vdi.size = 0 

270 vdi.utilisation = 0 

271 vdi._db_introduce() 

272 self.run_corner_cases_tests() 

273 return vdi.get_params() 

274 

275 def check_no_other_vdi_operation_in_progress(self): 

276 vdis = util.list_VDI_records_in_sr(self.sr) 

277 vdi_ref = self.session.xenapi.VDI.get_by_uuid(self.uuid) 

278 del vdis[vdi_ref] 

279 active_vdis = [v for v in list(vdis.values()) if v['current_operations'] != {}] 

280 if len(active_vdis) != 0: 

281 msg = "LVHDRT: found other operations in progress for VDI: %s" % active_vdis[0]['uuid'] 

282 util.SMlog(msg) 

283 raise xs_errors.XenError('VDIInUse') 

284 

285 def get_attached_vbds(self): 

286 vdi_ref = self.session.xenapi.VDI.get_by_uuid(self.uuid) 

287 vbds = self.session.xenapi.VBD.get_all_records_where("field \"VDI\" = \"%s\"" % vdi_ref) 

288 return [v for v in list(vbds.values()) if v['currently_attached'] == "true"] 

289 

290 def check_vbd_list_is_stable(self, attached_vbds): 

291 newly_attached_vbds = self.get_attached_vbds() 

292 old_set = set(attached_vbds) 

293 new_set = set(newly_attached_vbds) 

294 diff_set = old_set.difference(new_set) | new_set.difference(old_set) 

295 if len(diff_set) != 0: 

296 msg = "LVHDRT: found a non-stable VBD: %s" % (diff_set.pop()) 

297 util.SMlog(msg) 

298 raise xs_errors.XenError('VBDListNotStable') 

299 

300 def run_corner_cases_tests(self): 

301 

302 def fn(): 

303 attached_vbds = self.get_attached_vbds() 

304 for i in range(0, 10): 

305 time.sleep(2) 

306 self.check_no_other_vdi_operation_in_progress() 

307 self.check_vbd_list_is_stable(attached_vbds) 

308 

309 util.fistpoint.activate_custom_fn("LVHDRT_xapiSM_serialization_tests", fn) 

310 

311if __name__ == '__main__': 311 ↛ 312line 311 didn't jump to line 312, because the condition on line 311 was never true

312 SRCommand.run(DummySR, DRIVER_INFO) 

313else: 

314 SR.registerSR(DummySR)