summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/testmanager/core/buildblacklist.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/ValidationKit/testmanager/core/buildblacklist.py
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/ValidationKit/testmanager/core/buildblacklist.py')
-rwxr-xr-xsrc/VBox/ValidationKit/testmanager/core/buildblacklist.py324
1 files changed, 324 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/testmanager/core/buildblacklist.py b/src/VBox/ValidationKit/testmanager/core/buildblacklist.py
new file mode 100755
index 00000000..487fb9f0
--- /dev/null
+++ b/src/VBox/ValidationKit/testmanager/core/buildblacklist.py
@@ -0,0 +1,324 @@
+# -*- coding: utf-8 -*-
+# $Id: buildblacklist.py $
+
+"""
+Test Manager - Builds Blacklist.
+"""
+
+__copyright__ = \
+"""
+Copyright (C) 2012-2023 Oracle and/or its affiliates.
+
+This file is part of VirtualBox base platform packages, as
+available from https://www.virtualbox.org.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation, in version 3 of the
+License.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <https://www.gnu.org/licenses>.
+
+The contents of this file may alternatively be used under the terms
+of the Common Development and Distribution License Version 1.0
+(CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+in the VirtualBox distribution, in which case the provisions of the
+CDDL are applicable instead of those of the GPL.
+
+You may elect to license modified versions of this file under the
+terms and conditions of either the GPL or the CDDL or both.
+
+SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+"""
+__version__ = "$Revision: 155244 $"
+
+
+# Validation Kit imports.
+from testmanager.core.base import ModelDataBase, ModelLogicBase, TMInvalidData, TMRowNotFound;
+
+
+class BuildBlacklistData(ModelDataBase):
+ """
+ Build Blacklist Data.
+ """
+
+ ksIdAttr = 'idBlacklisting';
+
+ ksParam_idBlacklisting = 'BuildBlacklist_idBlacklisting'
+ ksParam_tsEffective = 'BuildBlacklist_tsEffective'
+ ksParam_tsExpire = 'BuildBlacklist_tsExpire'
+ ksParam_uidAuthor = 'BuildBlacklist_uidAuthor'
+ ksParam_idFailureReason = 'BuildBlacklist_idFailureReason'
+ ksParam_sProduct = 'BuildBlacklist_sProduct'
+ ksParam_sBranch = 'BuildBlacklist_sBranch'
+ ksParam_asTypes = 'BuildBlacklist_asTypes'
+ ksParam_asOsArches = 'BuildBlacklist_asOsArches'
+ ksParam_iFirstRevision = 'BuildBlacklist_iFirstRevision'
+ ksParam_iLastRevision = 'BuildBlacklist_iLastRevision'
+
+ kasAllowNullAttributes = [ 'idBlacklisting',
+ 'tsEffective',
+ 'tsExpire',
+ 'uidAuthor',
+ 'asTypes',
+ 'asOsArches' ];
+
+ def __init__(self):
+ ModelDataBase.__init__(self);
+
+ #
+ # Initialize with defaults.
+ # See the database for explanations of each of these fields.
+ #
+ self.idBlacklisting = None
+ self.tsEffective = None
+ self.tsExpire = None
+ self.uidAuthor = None
+ self.idFailureReason = None
+ self.sProduct = None
+ self.sBranch = None
+ self.asTypes = None
+ self.asOsArches = None
+ self.iFirstRevision = None
+ self.iLastRevision = None
+
+ def initFromDbRow(self, aoRow):
+ """
+ Re-initializes the data with a row from a SELECT * FROM BuildBlacklist.
+
+ Returns self. Raises exception if the row is None or otherwise invalid.
+ """
+
+ if aoRow is None:
+ raise TMRowNotFound('Build Blacklist item not found.')
+
+ self.idBlacklisting = aoRow[0]
+ self.tsEffective = aoRow[1]
+ self.tsExpire = aoRow[2]
+ self.uidAuthor = aoRow[3]
+ self.idFailureReason = aoRow[4]
+ self.sProduct = aoRow[5]
+ self.sBranch = aoRow[6]
+ self.asTypes = aoRow[7]
+ self.asOsArches = aoRow[8]
+ self.iFirstRevision = aoRow[9]
+ self.iLastRevision = aoRow[10]
+
+ return self;
+
+ def initFromDbWithId(self, oDb, idBlacklisting, tsNow = None, sPeriodBack = None):
+ """
+ Initialize the object from the database.
+ """
+ oDb.execute(self.formatSimpleNowAndPeriodQuery(oDb,
+ 'SELECT *\n'
+ 'FROM BuildBlacklist\n'
+ 'WHERE idBlacklisting = %s\n'
+ , ( idBlacklisting,), tsNow, sPeriodBack));
+ aoRow = oDb.fetchOne()
+ if aoRow is None:
+ raise TMRowNotFound('idBlacklisting=%s not found (tsNow=%s sPeriodBack=%s)'
+ % (idBlacklisting, tsNow, sPeriodBack,));
+ return self.initFromDbRow(aoRow);
+
+
+class BuildBlacklistLogic(ModelLogicBase): # pylint: disable=too-few-public-methods
+ """
+ Build Back List logic.
+ """
+
+ def __init__(self, oDb):
+ ModelLogicBase.__init__(self, oDb)
+ self.dCache = None;
+
+ def fetchForListing(self, iStart, cMaxRows, tsNow, aiSortColumns = None):
+ """
+ Fetches Build Blacklist records.
+
+ Returns an array (list) of BuildBlacklistData items, empty list if none.
+ Raises exception on error.
+ """
+ _ = aiSortColumns;
+
+ if tsNow is None:
+ self._oDb.execute('SELECT *\n'
+ 'FROM BuildBlacklist\n'
+ 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
+ 'ORDER BY idBlacklisting DESC\n'
+ 'LIMIT %s OFFSET %s\n'
+ , (cMaxRows, iStart,));
+ else:
+ self._oDb.execute('SELECT *\n'
+ 'FROM BuildBlacklist\n'
+ 'WHERE tsExpire > %s\n'
+ ' AND tsEffective <= %s\n'
+ 'ORDER BY idBlacklisting DESC\n'
+ 'LIMIT %s OFFSET %s\n'
+ , (tsNow, tsNow, cMaxRows, iStart,));
+
+ aoRows = []
+ for aoRow in self._oDb.fetchAll():
+ aoRows.append(BuildBlacklistData().initFromDbRow(aoRow))
+ return aoRows
+
+ def addEntry(self, oData, uidAuthor, fCommit = False):
+ """
+ Adds a blacklisting to the database.
+ """
+ self._oDb.execute('INSERT INTO BuildBlacklist (\n'
+ ' uidAuthor,\n'
+ ' idFailureReason,\n'
+ ' sProduct,\n'
+ ' sBranch,\n'
+ ' asTypes,\n'
+ ' asOsArches,\n'
+ ' iFirstRevision,\n'
+ ' iLastRevision)\n'
+ 'VALUES (%s, %s, %s, %s, %s, %s, %s, %s)'
+ , ( uidAuthor,
+ oData.idFailureReason,
+ oData.sProduct,
+ oData.sBranch,
+ oData.asTypes,
+ oData.asOsArches,
+ oData.iFirstRevision,
+ oData.iLastRevision,) );
+ self._oDb.maybeCommit(fCommit);
+ return True
+
+ def editEntry(self, oData, uidAuthor, fCommit = False):
+ """
+ Modifies a blacklisting.
+ """
+
+ #
+ # Validate inputs and read in the old(/current) data.
+ #
+ assert isinstance(oData, BuildBlacklistData);
+ dErrors = oData.validateAndConvert(self._oDb, oData.ksValidateFor_Edit);
+ if dErrors:
+ raise TMInvalidData('editEntry invalid input: %s' % (dErrors,));
+
+ oOldData = BuildBlacklistData().initFromDbWithId(self._oDb, oData.idBlacklisting);
+
+ #
+ # Update the data that needs updating.
+ #
+ if not oData.isEqualEx(oOldData, [ 'tsEffective', 'tsExpire', 'uidAuthor', ]):
+ self._historizeEntry(oData.idBlacklisting, None);
+ self._readdEntry(uidAuthor, oData, None);
+ self._oDb.maybeCommit(fCommit);
+ return True;
+
+
+ def removeEntry(self, uidAuthor, idBlacklisting, fCascade = False, fCommit = False):
+ """
+ Deletes a test group.
+ """
+ _ = fCascade; # Not applicable.
+
+ oData = BuildBlacklistData().initFromDbWithId(self._oDb, idBlacklisting);
+
+ (tsCur, tsCurMinusOne) = self._oDb.getCurrentTimestamps();
+ if oData.tsEffective not in (tsCur, tsCurMinusOne):
+ self._historizeEntry(idBlacklisting, tsCurMinusOne);
+ self._readdEntry(uidAuthor, oData, tsCurMinusOne);
+ self._historizeEntry(idBlacklisting);
+ self._oDb.execute('UPDATE BuildBlacklist\n'
+ 'SET tsExpire = CURRENT_TIMESTAMP\n'
+ 'WHERE idBlacklisting = %s\n'
+ ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
+ , (idBlacklisting,));
+ self._oDb.maybeCommit(fCommit);
+ return True;
+
+
+ def cachedLookup(self, idBlacklisting):
+ """
+ Looks up the most recent BuildBlacklistData object for idBlacklisting
+ via an object cache.
+
+ Returns a shared BuildBlacklistData object. None if not found.
+ Raises exception on DB error.
+ """
+ if self.dCache is None:
+ self.dCache = self._oDb.getCache('BuildBlacklistData');
+ oEntry = self.dCache.get(idBlacklisting, None);
+ if oEntry is None:
+ self._oDb.execute('SELECT *\n'
+ 'FROM BuildBlacklist\n'
+ 'WHERE idBlacklisting = %s\n'
+ ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
+ , (idBlacklisting, ));
+ if self._oDb.getRowCount() == 0:
+ # Maybe it was deleted, try get the last entry.
+ self._oDb.execute('SELECT *\n'
+ 'FROM BuildBlacklist\n'
+ 'WHERE idBlacklisting = %s\n'
+ 'ORDER BY tsExpire DESC\n'
+ 'LIMIT 1\n'
+ , (idBlacklisting, ));
+ elif self._oDb.getRowCount() > 1:
+ raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), idBlacklisting));
+
+ if self._oDb.getRowCount() == 1:
+ aaoRow = self._oDb.fetchOne();
+ oEntry = BuildBlacklistData();
+ oEntry.initFromDbRow(aaoRow);
+ self.dCache[idBlacklisting] = oEntry;
+ return oEntry;
+
+
+ #
+ # Helpers.
+ #
+
+ def _historizeEntry(self, idBlacklisting, tsExpire = None):
+ """
+ Historizes the current entry for the given backlisting.
+ """
+ if tsExpire is None:
+ tsExpire = self._oDb.getCurrentTimestamp();
+ self._oDb.execute('UPDATE BuildBlacklist\n'
+ 'SET tsExpire = %s\n'
+ 'WHERE idBlacklisting = %s\n'
+ ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
+ , ( tsExpire, idBlacklisting, ));
+ return True;
+
+ def _readdEntry(self, uidAuthor, oData, tsEffective = None):
+ """
+ Re-adds the BuildBlacklist entry. Used by editEntry and removeEntry.
+ """
+ if tsEffective is None:
+ tsEffective = self._oDb.getCurrentTimestamp();
+ self._oDb.execute('INSERT INTO BuildBlacklist (\n'
+ ' uidAuthor,\n'
+ ' tsEffective,\n'
+ ' idBlacklisting,\n'
+ ' idFailureReason,\n'
+ ' sProduct,\n'
+ ' sBranch,\n'
+ ' asTypes,\n'
+ ' asOsArches,\n'
+ ' iFirstRevision,\n'
+ ' iLastRevision)\n'
+ 'VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)\n'
+ , ( uidAuthor,
+ tsEffective,
+ oData.idBlacklisting,
+ oData.idFailureReason,
+ oData.sProduct,
+ oData.sBranch,
+ oData.asTypes,
+ oData.asOsArches,
+ oData.iFirstRevision,
+ oData.iLastRevision,) );
+ return True;
+