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 

20import SR 

21import VDI 

22import SRCommand 

23import util 

24import time 

25import xs_errors 

26 

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

28 "VDI_ACTIVATE", "VDI_DEACTIVATE", "VDI_CLONE", "VDI_SNAPSHOT", "VDI_RESIZE", 

29 "VDI_INTRODUCE", "VDI_MIRROR"] 

30 

31CONFIGURATION = [] 

32 

33DRIVER_INFO = { 

34 'name': 'dummy', 

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

36 'vendor': 'Citrix Systems Inc', 

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

38 'driver_version': '1.0', 

39 'required_api_version': '1.1', 

40 'capabilities': CAPABILITIES, 

41 'configuration': CONFIGURATION 

42 } 

43 

44TYPE = 'dummy' 

45 

46 

47class DummySR(SR.SR): 

48 """dummy storage repository""" 

49 

50 def handles(type): 

51 if type == TYPE: 

52 return True 

53 return False 

54 handles = staticmethod(handles) 

55 

56 def load(self, sr_uuid): 

57 self.sr_vditype = 'phy' 

58 

59 def content_type(self, sr_uuid): 

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

61 

62 def create(self, sr_uuid, size): 

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

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

65 

66 def delete(self, sr_uuid): 

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

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

69 

70 def attach(self, sr_uuid): 

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

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

73 

74 def detach(self, sr_uuid): 

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

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

77 

78 def probe(self): 

79 # N.B. There are no SR references 

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

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

82 

83 # Create some Dummy SR records 

84 entry = {} 

85 entry['size'] = 1024 

86 SRlist = {} 

87 SRlist[util.gen_uuid()] = entry 

88 

89 # Return the Probe XML 

90 return util.SRtoXML(SRlist) 

91 

92 def vdi(self, uuid): 

93 return DummyVDI(self, uuid) 

94 

95 def scan(self, sr_uuid): 

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

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

98 

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

100 for v in self._getallVDIrecords(): 

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

102 x.size = v['virtual_size'] 

103 x.utilisation = v['physical_utilisation'] 

104 self.vdis[x.uuid] = x 

105 

106 self.physical_size = 2000000000000 

107 self.physical_utilisation = 0 

108 self.virtual_allocation = 0 

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

110 

111 def _assertValues(self, vals): 

112 for attr in vals: 

113 assert(attr in self.srcmd.params) 

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

115 

116 # Iterate through the device_config dictionary 

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

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

119 

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

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

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

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

124 

125 def _getallVDIrecords(self): 

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

127 stored in the XenAPI server""" 

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

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

130 # We only need the VDIs corresponding to this SR 

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

132 

133 

134class DummyVDI(VDI.VDI): 

135 def load(self, vdi_uuid): 

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

137 self.uuid = vdi_uuid 

138 self.size = 0 

139 self.utilisation = 0 

140 self.location = vdi_uuid 

141 self.sm_config = {} 

142 

143 def create(self, sr_uuid, vdi_uuid, size): 

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

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

146 

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

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

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

150 

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

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

153 raise xs_errors.XenError('VDIExists') 

154 

155 self.size = size 

156 self.utilisation = size 

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

158 self._db_introduce() 

159 self.run_corner_cases_tests() 

160 return self.get_params() 

161 

162 def delete(self, sr_uuid, vdi_uuid): 

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

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

165 

166 # Assert that the VDI record exists 

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

168 self.run_corner_cases_tests() 

169 self._db_forget() 

170 

171 def introduce(self, sr_uuid, vdi_uuid): 

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

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

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

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

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

177 

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

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

180 raise xs_errors.XenError('VDIExists') 

181 self.uuid = vdi_uuid 

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

183 self._db_introduce() 

184 self.run_corner_cases_tests() 

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

186 

187 def attach(self, sr_uuid, vdi_uuid): 

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

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

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

191 self.run_corner_cases_tests() 

192 return vdi 

193 

194 def detach(self, sr_uuid, vdi_uuid): 

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

196 self.run_corner_cases_tests() 

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

198 

199 def activate(self, sr_uuid, vdi_uuid): 

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

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

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

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

204 self.run_corner_cases_tests() 

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

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

207 

208 def deactivate(self, sr_uuid, vdi_uuid): 

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

210 self.run_corner_cases_tests() 

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

212 

213 def resize(self, sr_uuid, vdi_uuid, size): 

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

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

216 

217 self.size = size 

218 self.utilisation = size 

219 self._db_update() 

220 self.run_corner_cases_tests() 

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

222 

223 def snapshot(self, sr_uuid, vdi_uuid): 

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

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

226 

227 dest = util.gen_uuid() 

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

229 vdi.read_only = True 

230 vdi.location = dest 

231 vdi.size = 0 

232 vdi.utilisation = 0 

233 vdi._db_introduce() 

234 self.run_corner_cases_tests() 

235 return vdi.get_params() 

236 

237 def clone(self, sr_uuid, vdi_uuid): 

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

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

240 

241 dest = util.gen_uuid() 

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

243 vdi.read_only = False 

244 vdi.location = dest 

245 vdi.size = 0 

246 vdi.utilisation = 0 

247 vdi._db_introduce() 

248 self.run_corner_cases_tests() 

249 return vdi.get_params() 

250 

251 def check_no_other_vdi_operation_in_progress(self): 

252 vdis = util.list_VDI_records_in_sr(self.sr) 

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

254 del vdis[vdi_ref] 

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

256 if len(active_vdis) != 0: 

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

258 util.SMlog(msg) 

259 raise xs_errors.XenError('OtherVDIOperationInProgress') 

260 

261 def get_attached_vbds(self): 

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

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

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

265 

266 def check_vbd_list_is_stable(self, attached_vbds): 

267 newly_attached_vbds = self.get_attached_vbds() 

268 old_set = set(attached_vbds) 

269 new_set = set(newly_attached_vbds) 

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

271 if len(diff_set) != 0: 

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

273 util.SMlog(msg) 

274 raise xs_errors.XenError('VBDListNotStable') 

275 

276 def run_corner_cases_tests(self): 

277 

278 def fn(): 

279 attached_vbds = self.get_attached_vbds() 

280 for i in range(0, 10): 

281 time.sleep(2) 

282 self.check_no_other_vdi_operation_in_progress() 

283 self.check_vbd_list_is_stable(attached_vbds) 

284 

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

286 

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

288 SRCommand.run(DummySR, DRIVER_INFO) 

289else: 

290 SR.registerSR(DummySR)