VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/core/globalresource.py@ 107349

Last change on this file since 107349 was 106061, checked in by vboxsync, 5 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.2 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: globalresource.py 106061 2024-09-16 14:03:52Z vboxsync $
3
4"""
5Test Manager - Global Resources.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2024 Oracle and/or its affiliates.
11
12This file is part of VirtualBox base platform packages, as
13available from https://www.virtualbox.org.
14
15This program is free software; you can redistribute it and/or
16modify it under the terms of the GNU General Public License
17as published by the Free Software Foundation, in version 3 of the
18License.
19
20This program is distributed in the hope that it will be useful, but
21WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with this program; if not, see <https://www.gnu.org/licenses>.
27
28The contents of this file may alternatively be used under the terms
29of the Common Development and Distribution License Version 1.0
30(CDDL), a copy of it is provided in the "COPYING.CDDL" file included
31in the VirtualBox distribution, in which case the provisions of the
32CDDL are applicable instead of those of the GPL.
33
34You may elect to license modified versions of this file under the
35terms and conditions of either the GPL or the CDDL or both.
36
37SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
38"""
39__version__ = "$Revision: 106061 $"
40
41
42# Standard python imports.
43import unittest;
44
45# Validation Kit imports.
46from testmanager.core.base import ModelDataBase, ModelDataBaseTestCase, ModelLogicBase, TMRowNotFound;
47
48
49class GlobalResourceData(ModelDataBase):
50 """
51 Global resource data
52 """
53
54 ksIdAttr = 'idGlobalRsrc';
55
56 ksParam_idGlobalRsrc = 'GlobalResource_idGlobalRsrc'
57 ksParam_tsEffective = 'GlobalResource_tsEffective'
58 ksParam_tsExpire = 'GlobalResource_tsExpire'
59 ksParam_uidAuthor = 'GlobalResource_uidAuthor'
60 ksParam_sName = 'GlobalResource_sName'
61 ksParam_sDescription = 'GlobalResource_sDescription'
62 ksParam_fEnabled = 'GlobalResource_fEnabled'
63
64 kasAllowNullAttributes = ['idGlobalRsrc', 'tsEffective', 'tsExpire', 'uidAuthor', 'sDescription' ];
65 kcchMin_sName = 2;
66 kcchMax_sName = 64;
67
68 def __init__(self):
69 ModelDataBase.__init__(self);
70
71 #
72 # Initialize with defaults.
73 # See the database for explanations of each of these fields.
74 #
75 self.idGlobalRsrc = None;
76 self.tsEffective = None;
77 self.tsExpire = None;
78 self.uidAuthor = None;
79 self.sName = None;
80 self.sDescription = None;
81 self.fEnabled = False
82
83 def initFromDbRow(self, aoRow):
84 """
85 Reinitialize from a SELECT * FROM GlobalResources row.
86 Returns self. Raises exception if no row.
87 """
88 if aoRow is None:
89 raise TMRowNotFound('Global resource not found.')
90
91 self.idGlobalRsrc = aoRow[0]
92 self.tsEffective = aoRow[1]
93 self.tsExpire = aoRow[2]
94 self.uidAuthor = aoRow[3]
95 self.sName = aoRow[4]
96 self.sDescription = aoRow[5]
97 self.fEnabled = aoRow[6]
98 return self
99
100 def initFromDbWithId(self, oDb, idGlobalRsrc, tsNow = None, sPeriodBack = None):
101 """
102 Initialize the object from the database.
103 """
104 oDb.execute(self.formatSimpleNowAndPeriodQuery(oDb,
105 'SELECT *\n'
106 'FROM GlobalResources\n'
107 'WHERE idGlobalRsrc = %s\n'
108 , ( idGlobalRsrc,), tsNow, sPeriodBack));
109 aoRow = oDb.fetchOne()
110 if aoRow is None:
111 raise TMRowNotFound('idGlobalRsrc=%s not found (tsNow=%s sPeriodBack=%s)' % (idGlobalRsrc, tsNow, sPeriodBack,));
112 return self.initFromDbRow(aoRow);
113
114 def isEqual(self, oOther):
115 """
116 Compares two instances.
117 """
118 return self.idGlobalRsrc == oOther.idGlobalRsrc \
119 and str(self.tsEffective) == str(oOther.tsEffective) \
120 and str(self.tsExpire) == str(oOther.tsExpire) \
121 and self.uidAuthor == oOther.uidAuthor \
122 and self.sName == oOther.sName \
123 and self.sDescription == oOther.sDescription \
124 and self.fEnabled == oOther.fEnabled
125
126
127class GlobalResourceLogic(ModelLogicBase):
128 """
129 Global resource logic.
130 """
131
132 def __init__(self, oDb):
133 ModelLogicBase.__init__(self, oDb)
134 self.dCache = None;
135
136 def fetchForListing(self, iStart, cMaxRows, tsNow, aiSortColumns = None):
137 """
138 Returns an array (list) of FailureReasonData items, empty list if none.
139 Raises exception on error.
140 """
141 _ = aiSortColumns;
142
143 if tsNow is None:
144 self._oDb.execute('SELECT *\n'
145 'FROM GlobalResources\n'
146 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
147 'ORDER BY idGlobalRsrc DESC\n'
148 'LIMIT %s OFFSET %s\n'
149 , (cMaxRows, iStart,));
150 else:
151 self._oDb.execute('SELECT *\n'
152 'FROM GlobalResources\n'
153 'WHERE tsExpire > %s\n'
154 ' AND tsEffective <= %s\n'
155 'ORDER BY idGlobalRsrc DESC\n'
156 'LIMIT %s OFFSET %s\n'
157 , (tsNow, tsNow, cMaxRows, iStart,))
158
159 aoRows = []
160 for aoRow in self._oDb.fetchAll():
161 aoRows.append(GlobalResourceData().initFromDbRow(aoRow))
162 return aoRows
163
164
165 def cachedLookup(self, idGlobalRsrc):
166 """
167 Looks up the most recent GlobalResourceData object for idGlobalRsrc
168 via an object cache.
169
170 Returns a shared GlobalResourceData object. None if not found.
171 Raises exception on DB error.
172 """
173 if self.dCache is None:
174 self.dCache = self._oDb.getCache('GlobalResourceData');
175 oEntry = self.dCache.get(idGlobalRsrc, None);
176 if oEntry is None:
177 self._oDb.execute('SELECT *\n'
178 'FROM GlobalResources\n'
179 'WHERE idGlobalRsrc = %s\n'
180 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
181 , (idGlobalRsrc, ));
182 if self._oDb.getRowCount() == 0:
183 # Maybe it was deleted, try get the last entry.
184 self._oDb.execute('SELECT *\n'
185 'FROM GlobalResources\n'
186 'WHERE idGlobalRsrc = %s\n'
187 'ORDER BY tsExpire DESC\n'
188 'LIMIT 1\n'
189 , (idGlobalRsrc, ));
190 elif self._oDb.getRowCount() > 1:
191 raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), idGlobalRsrc));
192
193 if self._oDb.getRowCount() == 1:
194 aaoRow = self._oDb.fetchOne();
195 oEntry = GlobalResourceData();
196 oEntry.initFromDbRow(aaoRow);
197 self.dCache[idGlobalRsrc] = oEntry;
198 return oEntry;
199
200
201 def getAll(self, tsEffective = None):
202 """
203 Gets all global resources.
204
205 Returns an array of GlobalResourceData instances on success (can be
206 empty). Raises exception on database error.
207 """
208 if tsEffective is not None:
209 self._oDb.execute('SELECT *\n'
210 'FROM GlobalResources\n'
211 'WHERE tsExpire > %s\n'
212 ' AND tsEffective <= %s\n'
213 , (tsEffective, tsEffective));
214 else:
215 self._oDb.execute('SELECT *\n'
216 'FROM GlobalResources\n'
217 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n');
218 aaoRows = self._oDb.fetchAll();
219 aoRet = [];
220 for aoRow in aaoRows:
221 aoRet.append(GlobalResourceData().initFromDbRow(aoRow));
222
223 return aoRet;
224
225 def addGlobalResource(self, uidAuthor, oData):
226 """Add Global Resource DB record"""
227 self._oDb.execute('SELECT * FROM add_globalresource(%s, %s, %s, %s);',
228 (uidAuthor,
229 oData.sName,
230 oData.sDescription,
231 oData.fEnabled))
232 self._oDb.commit()
233 return True
234
235 def editGlobalResource(self, uidAuthor, idGlobalRsrc, oData):
236 """Modify Global Resource DB record"""
237 # Check if anything has been changed
238 oGlobalResourcesDataOld = self.getById(idGlobalRsrc)
239 if oGlobalResourcesDataOld.isEqual(oData):
240 # Nothing has been changed, do nothing
241 return True
242
243 self._oDb.execute('SELECT * FROM update_globalresource(%s, %s, %s, %s, %s);',
244 (uidAuthor,
245 idGlobalRsrc,
246 oData.sName,
247 oData.sDescription,
248 oData.fEnabled))
249 self._oDb.commit()
250 return True
251
252 def remove(self, uidAuthor, idGlobalRsrc):
253 """Delete Global Resource DB record"""
254 self._oDb.execute('SELECT * FROM del_globalresource(%s, %s);',
255 (uidAuthor, idGlobalRsrc))
256 self._oDb.commit()
257 return True
258
259 def getById(self, idGlobalRsrc):
260 """
261 Get global resource record by its id
262 """
263 self._oDb.execute('SELECT *\n'
264 'FROM GlobalResources\n'
265 'WHERE tsExpire = \'infinity\'::timestamp\n'
266 ' AND idGlobalRsrc=%s;', (idGlobalRsrc,))
267
268 aRows = self._oDb.fetchAll()
269 if len(aRows) not in (0, 1):
270 raise self._oDb.integrityException('Duplicate global resource entry with ID %u (current)' % (idGlobalRsrc,));
271 try:
272 return GlobalResourceData().initFromDbRow(aRows[0])
273 except IndexError:
274 raise TMRowNotFound('Global resource not found.')
275
276 def allocateResources(self, idTestBox, aoGlobalRsrcs, fCommit = False):
277 """
278 Allocates the given global resource.
279
280 Returns True of successfully allocated the resources, False if not.
281 May raise exception on DB error.
282 """
283 # Quit quickly if there is nothing to alloocate.
284 if not aoGlobalRsrcs:
285 return True;
286
287 #
288 # Note! Someone else might have allocated the resources since the
289 # scheduler check that they were available. In such case we
290 # need too quietly rollback and return FALSE.
291 #
292 self._oDb.execute('SAVEPOINT allocateResources');
293
294 for oGlobalRsrc in aoGlobalRsrcs:
295 try:
296 self._oDb.execute('INSERT INTO GlobalResourceStatuses (idGlobalRsrc, idTestBox)\n'
297 'VALUES (%s, %s)', (oGlobalRsrc.idGlobalRsrc, idTestBox, ) );
298 except self._oDb.oXcptError:
299 self._oDb.execute('ROLLBACK TO SAVEPOINT allocateResources');
300 return False;
301
302 self._oDb.execute('RELEASE SAVEPOINT allocateResources');
303 self._oDb.maybeCommit(fCommit);
304 return True;
305
306 def freeGlobalResourcesByTestBox(self, idTestBox, fCommit = False):
307 """
308 Frees all global resources own by the given testbox.
309 Returns True. May raise exception on DB error.
310 """
311 self._oDb.execute('DELETE FROM GlobalResourceStatuses\n'
312 'WHERE idTestBox = %s\n', (idTestBox, ) );
313 self._oDb.maybeCommit(fCommit);
314 return True;
315
316#
317# Unit testing.
318#
319
320# pylint: disable=missing-docstring
321class GlobalResourceDataTestCase(ModelDataBaseTestCase):
322 def setUp(self):
323 self.aoSamples = [GlobalResourceData(),];
324
325if __name__ == '__main__':
326 unittest.main();
327 # not reached.
328
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette