To receive notifications about scheduled maintenance, please subscribe to the mailing-list gitlab-operations@sympa.ethz.ch. You can subscribe to the mailing-list at https://sympa.ethz.ch

Commit 4078d5b5 authored by Reto Da Forno's avatar Reto Da Forno

is_admin field in renamed to 'role' (valid roles are 'user', 'admin' and 'internal')

parent 4a78a5d8
......@@ -155,7 +155,7 @@ CREATE TABLE `tbl_serv_observer` (
`serv_observer_key` int(10) unsigned NOT NULL AUTO_INCREMENT,
`ethernet_address` varchar(60) COLLATE utf8_bin NOT NULL,
`observer_id` int(11) NOT NULL,
`status` enum('online','offline','disabled','develop') COLLATE utf8_bin NOT NULL DEFAULT 'disabled',
`status` enum('online','offline','disabled','develop', 'internal') COLLATE utf8_bin NOT NULL DEFAULT 'disabled',
`slot_1_tg_adapt_list_fk` int(10) unsigned DEFAULT NULL,
`slot_2_tg_adapt_list_fk` int(10) unsigned DEFAULT NULL,
`slot_3_tg_adapt_list_fk` int(10) unsigned DEFAULT NULL,
......@@ -435,12 +435,12 @@ CREATE TABLE `tbl_serv_users` (
`country` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`institution_type` varchar(20) COLLATE utf8_unicode_ci NOT NULL COMMENT 'One of university, research institute, other',
`institution_type` ENUM('university', 'researchinstitute', 'company', 'other') NOT NULL DEFAULT 'other',
`institution` varchar(500) COLLATE utf8_unicode_ci NOT NULL,
`quota_runtime` int(11) NOT NULL DEFAULT '60' COMMENT 'Runtime per test in minutes',
`quota_tests` int(11) NOT NULL DEFAULT '3' COMMENT 'Max no. of tests to be scheduled',
`retention_time` int(11) NOT NULL DEFAULT '60' COMMENT 'Retention time for testresults in days. After this time, all testresults are deleted. A value of -1 means that tests should be kept infinitely.',
`is_admin` tinyint(4) NOT NULL DEFAULT '0',
`role` ENUM('user', 'admin', 'internal') NOT NULL DEFAULT 'user',
`is_active` tinyint(4) NOT NULL DEFAULT '1',
`create_time` datetime NOT NULL,
`last_login` datetime DEFAULT NULL,
......
......@@ -897,7 +897,7 @@ def get_admin_emails(cursor=None, config=None):
# Get the addresses from the database:
try:
cursor.execute("SELECT `email` FROM `tbl_serv_users` WHERE `is_admin` = 1")
cursor.execute("SELECT `email` FROM `tbl_serv_users` WHERE `role` = 'admin'")
rs = cursor.fetchall()
for mail in rs:
email_list.append(mail[0])
......
......@@ -177,10 +177,10 @@ def is_admin(cursor=None, userid=0):
# Get the addresses from the database:
try:
cursor.execute("SELECT `is_admin` FROM `tbl_serv_users` WHERE `serv_users_key` = %d" %userid)
cursor.execute("SELECT `role` FROM `tbl_serv_users` WHERE `serv_users_key` = %d" %userid)
rs = cursor.fetchone()
ret = False
if ((rs != None) and (rs[0] == 1)):
if ((rs != None) and (rs[0] == 'admin')):
ret = True
except:
# There was an error in the database connection:
......@@ -191,6 +191,40 @@ def is_admin(cursor=None, userid=0):
### END is_admin()
##############################################################################
#
# get_role - Check if an ID belongs to an internal user.
#
##############################################################################
def is_internal(cursor=None, userid=0):
"""Arguments:
cursor: cursor of the database connection to be used for the query
userid: user ID to test
Return value:
On success, True or False
1 if there is an error in the arguments passed to the function
2 if there was an error in processing the request
"""
# Check the arguments:
if ((type(cursor) != MySQLdb.cursors.Cursor) or (type(userid) != int) or (userid <= 0)):
return(1)
# Get the addresses from the database:
try:
cursor.execute("SELECT `role` FROM `tbl_serv_users` WHERE `serv_users_key` = %d" %userid)
rs = cursor.fetchone()
ret = False
if ((rs != None) and (rs[0] == 'internal')):
ret = True
except:
# There was an error in the database connection:
syslog(LOG_WARNING, "FlockLab is_internal() error: %s: %s" %(str(sys.exc_info()[0]), str(sys.exc_info()[1])))
return(2)
return ret
### END is_internal()
##############################################################################
#
# get_testowner_email - Get the email address of the owner of a particular
......
......@@ -133,6 +133,7 @@ def main(argv):
schemapath = None
testid = None
isadmin = False
isinternal = False
# Open the log and create logger:
try:
......@@ -232,6 +233,12 @@ def main(argv):
logger.warn("Could not determine if user is admin or not. Error %d occurred. Exiting..." %isadmin)
sys.exit(errno.EAGAIN)
# Check if the user is internal:
isinternal = flocklab.is_internal(cursor, userid)
if isinternal not in (True, False):
logger.warn("Could not determine if user is internal or not. Error %d occurred. Exiting..." %isinternal)
sys.exit(errno.EAGAIN)
# Initialize error counter and set timezone to UTC:
errcnt = 0;
os.environ['TZ'] = 'UTC'
......@@ -289,7 +296,6 @@ def main(argv):
# * If specified, end time has to be after start time
f = open(xmlpath, 'r')
parser = etree.XMLParser(remove_comments=True)
#tree = etree.fromstring(f.read(), parser)
tree = etree.parse(f, parser)
f.close()
ns = {'d': config.get('xml', 'namespace')}
......@@ -510,6 +516,8 @@ def main(argv):
stati = "'online'"
if isadmin:
stati += ", 'develop'"
if isinternal:
stati += ", 'internal'"
cursor.execute(sql_adap %(obsid, stati))
adaptTypesFk = cursor.fetchone()
# If no results are returned, it most probably means that the observer is not active at the moment:
......
#!/usr/bin/env python
__author__ = "Christoph Walser <walserc@tik.ee.ethz.ch>, Adnan Mlika"
__copyright__ = "Copyright 2010, ETH Zurich, Switzerland"
__license__ = "GPL"
__version__ = "$Revision: 3133 $"
__date__ = "$Date: 2015-08-26 10:20:36 +0200 (Wed, 26 Aug 2015) $"
__id__ = "$Id: testconfig_validator.py 3133 2015-08-26 08:20:36Z rlim $"
__source__ = "$URL: svn://svn.ee.ethz.ch/flocklab/trunk/server/webserver/testmanagement/testconfig_validator.py $"
"""
!!!IMPORTANT!!! This file belongs to /home/flocklab/testmanagement/ on the FlockLab webserver
"""
import sys, os, getopt, errno, subprocess, time, calendar, MySQLdb, tempfile, base64, syslog, re
from lxml import etree
import logging.config
# Import local libraries:
scriptpath = os.path.dirname(os.path.abspath(sys.argv[0]))
sys.path.append(scriptpath + '/lib')
from flocklab import SUCCESS
import flocklab
### Global variables ###
###
version = filter(str.isdigit, __version__)
###
##############################################################################
#
# Error classes
#
##############################################################################
class Error(Exception):
""" Base class for exception. """
pass
### END Error classes
##############################################################################
#
# checkObsids
# Checks if every observer ID returned by the xpath evaluation is only used
# once and if every observer ID is in the list provided in obsidlist.
#
##############################################################################
def checkObsids(tree, xpathExpr, namespace, obsidlist=None):
duplicates = False
allInList = True
# Get the observer IDs from the xpath expression:
rs = tree.xpath(xpathExpr, namespaces=namespace)
# Build a list with all used observer IDs in it:
foundObsids = []
tmp = []
for ids in rs:
tmp.append(ids.text.split())
map(foundObsids.extend, tmp)
# Check for duplicates:
if ( (len(foundObsids) != len(set(foundObsids))) ):
duplicates = True
# Check if all obs ids are in the list:
for obsid in foundObsids:
if obsid not in obsidlist:
allInList = False
# Return the values to the caller:
if (duplicates or not allInList):
return(None, duplicates, allInList)
else:
return(sorted(foundObsids), duplicates, allInList)
### END checkObsids()
##############################################################################
#
# getXmlTimestamp
# Converts XML timestamps to python taking timezone into account.
#
##############################################################################
def getXmlTimestamp(datetimestring):
#is there a timezone?
m = re.match('([0-9]{4,4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2})([+-])([0-9]{2,2}):([0-9]{2,2})',datetimestring)
if m == None:
timestamp = calendar.timegm(time.strptime(datetimestring, "%Y-%m-%dT%H:%M:%SZ"))
else:
timestamp = calendar.timegm(time.strptime('%s' % (m.group(1)), "%Y-%m-%dT%H:%M:%S"))
offset = int(m.group(3))*3600 + int(m.group(4)) * 60
if m.group(2)=='-':
timestamp = timestamp + offset;
else:
timestamp = timestamp - offset;
return timestamp
### END getXmlTimestamp()
##############################################################################
#
# Usage
#
##############################################################################
def usage(config):
print "Usage: %s [--xml=<path>] [--testid=<int>] [--userid=<int>] [--schema=<path>] [--quiet] [--help] [--version]" % sys.argv[0]
print "Validate an XML testconfiguration. Returns 0 on success, errno on errors."
print "Options:"
print " --xml\t\t\t\tOptional. Path to the XML file which is to check. Either --xml or --testid are mandatory. If both are given, --testid will be favoured."
print " --testid\t\t\tOptional. Test ID to validate. If this parameter is set, the XML will be taken from the DB. Either --xml or --testid are mandatory. If both are given, --testid will be favoured."
print " --userid\t\t\tOptional. User ID to which the XML belongs. Mandatory if --xml is specified."
print " --schema\t\t\tOptional. Path to the XML schema to check XML against. If not given, the standard path will be used: %s" %(str(config.get('xml', 'schemapath')))
print " --quiet\t\t\tOptional. Do not print on standard out."
print " --help\t\t\tOptional. Print this help."
print " --version\t\t\tOptional. Print version number of software and exit."
### END usage()
##############################################################################
#
# Main
#
##############################################################################
def main(argv):
quiet = False
userid = None
xmlpath = None
schemapath = None
testid = None
isadmin = False
# Open the log and create logger:
try:
logging.config.fileConfig(scriptpath + '/logging.conf')
logger = logging.getLogger("testconfig_validator.py")
except:
syslog.syslog(syslog.LOG_ERR, "testconfig_validator.py: Could not open logger because: %s: %s" %(str(sys.exc_info()[0]), str(sys.exc_info()[1])))
# Get the config file:
config = flocklab.get_config()
if not config:
logger.warn("Could not read configuration file. Exiting...")
sys.exit(errno.EAGAIN)
# Get command line parameters.
try:
opts, args = getopt.getopt(argv, "hvqu:s:x:t:", ["help", "version", "quiet", "userid=", "schema=", "xml=", "testid="])
except getopt.GetoptError, err:
logger.warn(str(err))
usage(config)
sys.exit(errno.EINVAL)
for opt, arg in opts:
if opt in ("-u", "--userid"):
try:
userid = int(arg)
if userid <= 0:
raise Error
except:
logger.warn("Wrong API usage: userid has to be a positive number")
sys.exit(errno.EINVAL)
elif opt in ("-t", "--testid"):
try:
testid = int(arg)
if testid <= 0:
raise Error
except:
logger.warn("Wrong API usage: testid has to be a positive number")
sys.exit(errno.EINVAL)
elif opt in ("-s", "--schema"):
schemapath = arg
if (not os.path.exists(schemapath) or not os.path.isfile(schemapath)):
logger.warn("Wrong API usage: schema file does not exist")
sys.exit(errno.EINVAL)
elif opt in ("-x", "--xml"):
xmlpath = arg
if (not os.path.exists(xmlpath) or not os.path.isfile(xmlpath)):
logger.warn("Wrong API usage: XML file does not exist")
sys.exit(errno.EINVAL)
elif opt in ("-h", "--help"):
usage(config)
sys.exit(SUCCESS)
elif opt in ("-v", "--version"):
print version
sys.exit(SUCCESS)
elif opt in ("-q", "--quiet"):
quiet = True
else:
if not quiet:
print "Wrong API usage"
usage(config)
logger.warn("Wrong API usage")
sys.exit(errno.EINVAL)
# Check mandatory arguments:
if ( ((not testid) and (not xmlpath)) or ((xmlpath) and (not userid)) ):
if not quiet:
print "Wrong API usage"
usage(config)
logger.warn("Wrong API usage")
sys.exit(errno.EINVAL)
# Set the schemapath:
if not schemapath:
schemapath = config.get('xml', 'schemapath')
# Connect to the DB:
try:
db = MySQLdb.connect(host=config.get('database','host'), user=config.get('database','user'), passwd=config.get('database','password'), db=config.get('database','database'))
cursor = db.cursor()
except:
logger.warn("Could not connect to the database because: %s: %s" %(str(sys.exc_info()[0]), str(sys.exc_info()[1])))
sys.exit(errno.EAGAIN)
# Check if the user is admin:
isadmin = flocklab.is_admin(cursor, userid)
if isadmin not in (True, False):
logger.warn("Could not determine if user is admin or not. Error %d occurred. Exiting..." %isadmin)
sys.exit(errno.EAGAIN)
# Initialize error counter and set timezone to UTC:
errcnt = 0;
os.environ['TZ'] = 'UTC'
time.tzset()
#===========================================================================
# If a testid was given, get the xml from the database
#===========================================================================
if testid:
# Get the XML from the database, put it into a temp file and set the xmlpath accordingly:
(fd, xmlpath) = tempfile.mkstemp()
cursor.execute("SELECT `testconfig_xml`, `owner_fk` FROM `tbl_serv_tests` WHERE (`serv_tests_key` = %s)" %testid)
ret = cursor.fetchone()
if not ret:
if not quiet:
print "No test found in database with testid %d. Exiting..." %testid
errcnt = errcnt + 1
else:
xmlfile = os.fdopen(fd, 'w+b')
xmlfile.write(ret[0])
xmlfile.close()
userid = int(ret[1])
#===========================================================================
# Validate the XML against the XML schema
#===========================================================================
if errcnt == 0:
p = subprocess.Popen(['xmllint', '--noout', xmlpath, '--schema', schemapath], stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
for err in stderr.split('\n'):
tmp = err.split(':')
if len(tmp) >= 7:
if not quiet:
print "<b>Line " + tmp[1] + "</b>:" + tmp[2] + ":" + ":".join(tmp[6:])
errcnt = errcnt + 1
elif not ((err.find('fails to validate') != -1) or (err.find('validates') != -1) or (err == '\n') or (err == '')):
if not quiet:
print err
errcnt = errcnt + 1
#===========================================================================
# If XML is valid, do additional checks on <generalConf> and <targetConf> elements
#===========================================================================
if errcnt == 0:
# generalConf additional validation -------------------------------------------
# * If specified, start time has to be in the future
# * If specified, end time has to be after start time
f = open(xmlpath, 'r')
parser = etree.XMLParser(remove_comments=True)
tree = etree.parse(f, parser)
f.close()
ns = {'d': config.get('xml', 'namespace')}
# check xs:list items (obsIds, targetIds) for whitespace as separator
for l in tree.xpath('//d:*/d:obsIds', namespaces=ns) + tree.xpath('//d:*/d:targetIds', namespaces=ns):
if l.text.find('\t')>=0:
if not quiet:
print "<b>Element obsIds/targetIds</b>: Id lists must not have tabs as separators."
errcnt = errcnt + 1
if errcnt == 0:
sched_abs = tree.xpath('//d:generalConf/d:scheduleAbsolute', namespaces=ns)
sched_asap = tree.xpath('//d:generalConf/d:scheduleAsap', namespaces=ns)
if sched_abs:
# The start date and time have to be in the future:
rs = tree.xpath('//d:generalConf/d:scheduleAbsolute/d:start', namespaces=ns)
now = time.time()
testStart = getXmlTimestamp(rs[0].text)
if (testStart <= now):
if not quiet:
print "<b>Element generalConf</b>: Start time has to be in the future."
errcnt = errcnt + 1
# The end date and time have to be in the future and after the start:
rs = tree.xpath('//d:generalConf/d:scheduleAbsolute/d:end', namespaces=ns)
testEnd = getXmlTimestamp(rs[0].text)
if (testEnd <= testStart):
if not quiet:
print "<b>Element generalConf</b>: End time has to be after start time."
errcnt = errcnt + 1
# Calculate the test duration which is needed later on:
testDuration = testEnd - testStart
elif sched_asap:
testDuration = int(tree.xpath('//d:generalConf/d:scheduleAsap/d:durationSecs', namespaces=ns)[0].text)
# targetConf additional validation --------------------------------------------
# * DB image ids need to be in the database and binary field must not be empty
# * Embedded image ids need to be in elements in the XML and need to be valid and correct type
# * Observer ids need to have the correct target adaptor installed and must be unique
# * If specified, number of target ids need to be the same as observer ids
# * There must be a target image provided for every mandatory core (usually core 0, core 0-3 for DPP)
# Loop through all targetConf elements:
obsidlist = []
obsiddict = {}
targetconfs = tree.xpath('//d:targetConf', namespaces=ns)
for targetconf in targetconfs:
targetids = None
dbimageid = None
embimageid = None
moterunnerosonly = None
# Get elements:
obsids = targetconf.xpath('d:obsIds', namespaces=ns)[0].text.split()
ret = targetconf.xpath('d:targetIds', namespaces=ns)
if ret:
targetids = ret[0].text.split()
targetids_line = ret[0].sourceline
ret = targetconf.xpath('d:dbImageId', namespaces=ns)
if ret:
dbimageid = map(lambda o: o.text, ret)
dbimageid_line = map(lambda o: o.sourceline, ret)
ret = targetconf.xpath('d:embeddedImageId', namespaces=ns)
if ret:
embimageid = map(lambda o: o.text, ret)
embimageid_line = map(lambda o: o.sourceline, ret)
ret = targetconf.xpath('d:moterunnerOsOnly', namespaces=ns)
if ret:
moterunnerosonly = ret[0].text
moterunnerosonly_line = ret[0].sourceline
# Put obsids into obsidlist:
for obsid in obsids:
obsidlist.append(obsid)
# If target ids are present, there need to be as many as observer ids:
if (targetids and (len(targetids) != len(obsids))):
if not quiet:
print("<b>Line %d</b>: element targetIds: If element targetIds is used, it needs the same amount of IDs as in the corresponding element obsIds." %(targetids_line))
errcnt = errcnt + 1
# If DB image IDs are present, check if they are in the database and belong to the user (if he is not an admin) and get values for later use:
for dbimg, line in zip(dbimageid, dbimageid_line):
sql = """ SELECT b.name, c.name, a.core
FROM `tbl_serv_targetimages` AS a
LEFT JOIN `tbl_serv_operatingsystems` AS b
ON a.operatingsystems_fk = b.serv_operatingsystems_key
LEFT JOIN `tbl_serv_platforms` AS c
ON a.platforms_fk = c.serv_platforms_key
WHERE (a.`serv_targetimages_key` = %s AND a.`binary` IS NOT NULL)""" %(dbimg)
if not isadmin:
sql += " AND (a.`owner_fk` = %s)"%(userid)
cursor.execute(sql)
ret = cursor.fetchone()
if not ret:
if not quiet:
print("<b>Line %d</b>: element dbImageId: The image with ID %s does not exist in the database or does not belong to you." %(line, str(dbimg)))
errcnt = errcnt + 1
else:
# Put data into dictionary for later use:
core = int(ret[2])
for obsid in obsids:
if obsid not in obsiddict:
obsiddict[obsid] = {}
if core in obsiddict[obsid]:
if not quiet:
print("<b>Line %d</b>: element dbImageId: There is already an image for core %d (image with ID %s)." %(line, core, str(dbimg)))
errcnt = errcnt + 1
else:
obsiddict[obsid][core]=ret[:2]
# If embedded image IDs are present, check if they have a corresponding <imageConf> which is valid:
for embimg, line in zip(embimageid, embimageid_line):
imageconf = tree.xpath('//d:imageConf/d:embeddedImageId[text()="%s"]/..' %(embimg), namespaces=ns)
if not imageconf:
if not quiet:
print("<b>Line %d</b>: element embeddedImageId: There is no corresponding element imageConf with embeddedImageId %s defined." %(line, embimg))
errcnt = errcnt + 1
else:
# Get os and platform and put it into dictionary for later use:
opersys = imageconf[0].xpath('d:os', namespaces=ns)[0].text
platform = imageconf[0].xpath('d:platform', namespaces=ns)[0].text
core = int(imageconf[0].xpath('d:core', namespaces=ns)[0].text)
for obsid in obsids:
if obsid not in obsiddict:
obsiddict[obsid] = {}
if core in obsiddict[obsid]:
if not quiet:
print("<b>Line %d</b>: element dbImageId: There is already an image for core %d (image with ID %s)." %(line, core, str(embimg)))
errcnt = errcnt + 1
obsiddict[obsid][core]=(opersys, platform)
# Get the image and save it to a temporary file:
image = imageconf[0].xpath('d:data', namespaces=ns)[0].text
image_line = imageconf[0].xpath('d:data', namespaces=ns)[0].sourceline
(fd, imagefilename) = tempfile.mkstemp()
imagefile = os.fdopen(fd, 'w+b')
imagefile.write(base64.b64decode(image, None))
imagefile.close()
# Validate image:
p = subprocess.Popen([config.get('tests', 'testmanagementfolder') + '/targetimage_validator.py', '--quiet', '--image', imagefilename, '--os', opersys, '--platform', platform], stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != SUCCESS:
if not quiet:
print("<b>Line %d</b>: element data: Validation of image data failed. Check if elements os and platform are set correctly and if element <data> contains correct data." %(image_line))
errcnt = errcnt + 1
# Remove temporary file:
os.remove(imagefilename)
# If moterunner is to be used with OS only, do the necessary checks:
if moterunnerosonly:
opersys = 'moterunner'
# Check if moterunner is allowed to run on selected platform:
platform = targetconf.xpath('d:moterunnerOsOnly/d:platform', namespaces=ns)[0].text
allowed_platforms = ('iris', )
if (platform not in allowed_platforms):
if not quiet:
print("<b>Line %d</b>: element platform: only platforms %s can currently run moterunner." %(moterunnerosonly_line, ", ".join(allowed_platforms)))
errcnt = errcnt + 1
else:
for obsid in obsids:
obsiddict[obsid][0]=(opersys, platform)
# Check if no observers are in the list multiple times and if every observer has the correct target adapter installed:
obsidlist = list(set(obsidlist))
(obsids, duplicates, allInList) = checkObsids(tree, '//d:targetConf/d:obsIds', ns, obsidlist)
if duplicates:
if not quiet:
print "<b>Element targetConf</b>: Some observer IDs have been used more than once."
errcnt = errcnt + 1
else:
usedObsidsList = sorted(obsids)
# Now that we have the list, check the observer types:
sql_adap = """SELECT `b`.`tg_adapt_types_fk`, `c`.`tg_adapt_types_fk`, `d`.`tg_adapt_types_fk`, `e`.`tg_adapt_types_fk`
FROM `tbl_serv_observer` AS `a`
LEFT JOIN `tbl_serv_tg_adapt_list` AS `b` ON `a`.`slot_1_tg_adapt_list_fk` = `b`.`serv_tg_adapt_list_key`
LEFT JOIN `tbl_serv_tg_adapt_list` AS `c` ON `a`.`slot_2_tg_adapt_list_fk` = `c`.`serv_tg_adapt_list_key`
LEFT JOIN `tbl_serv_tg_adapt_list` AS `d` ON `a`.`slot_3_tg_adapt_list_fk` = `d`.`serv_tg_adapt_list_key`
LEFT JOIN `tbl_serv_tg_adapt_list` AS `e` ON `a`.`slot_4_tg_adapt_list_fk` = `e`.`serv_tg_adapt_list_key`
WHERE
(`a`.`observer_id` = %s)
AND (`a`.`status` IN (%s))
"""
sql_platf = """SELECT COUNT(*)
FROM `tbl_serv_tg_adapt_types` AS `a`
LEFT JOIN `tbl_serv_platforms` AS `b` ON `a`.`platforms_fk` = `b`.`serv_platforms_key`
WHERE
(`a`.`serv_tg_adapt_types_key` = %s)
AND (LOWER(`b`.`name`) = LOWER('%s'))
"""
sql_cores = """SELECT core, optional
FROM `tbl_serv_platforms` AS `b`
LEFT JOIN `tbl_serv_architectures` AS `a` ON `a`.`platforms_fk` = `b`.`serv_platforms_key`
WHERE (LOWER(`b`.`name`) = LOWER('%s'))
"""
for obsid in usedObsidsList:
if obsiddict.has_key(obsid):
platf = obsiddict[obsid].itervalues().next()[1].lower()
opersys = obsiddict[obsid].itervalues().next()[0].lower()
for p in obsiddict[obsid].itervalues():
if platf!=p[1].lower():
if not quiet:
print "<b>Element targetConf</b>: Observer ID %s has images of several platform types assigned." %(obsid)
errcnt = errcnt + 1
break
if opersys!=p[0].lower():
if not quiet:
print "<b>Element targetConf</b>: Observer ID %s has images of several operating system types assigned." %(obsid)
errcnt = errcnt + 1
break
else:
platf = None
# Get tg_adapt_types_fk of installed target adaptors on observer:
stati = "'online'"
if isadmin:
stati += ", 'develop'"
cursor.execute(sql_adap %(obsid, stati))
adaptTypesFk = cursor.fetchone()
# If no results are returned, it most probably means that the observer is not active at the moment:
if not adaptTypesFk:
if not quiet:
print "<b>Element targetConf</b>: Observer ID %s cannot be used at the moment." %(obsid)
errcnt = errcnt + 1
elif adaptTypesFk and platf:
# Cycle through the adaptors which are attached to the observer and try to find one that can be used with the requested platform:
adaptFound = False
for adapt in adaptTypesFk:
# Only check for entries which are not null:
if adapt:
cursor.execute(sql_platf %(adapt, platf))
rs = cursor.fetchone()
if (rs[0] > 0):
adaptFound = True
break
if not adaptFound:
if not quiet:
print "<b>Element targetConf</b>: Observer ID %s has currently no target adapter for %s installed." %(obsid, platf)
errcnt = errcnt + 1
if platf is not None:
cursor.execute(sql_cores %(platf))
core_info = cursor.fetchall()
all_cores = map(lambda row: row[0], core_info)
required_cores = map(lambda row: row[0], filter(lambda row: row[1]==0, core_info))
provided_cores = obsiddict[obsid].keys()
if not set(required_cores).issubset(set(provided_cores)):
if not quiet:
print "<b>Element targetConf</b>: Not enough target images provided for Observer ID %s. Platform %s requires images for cores %s." %(obsid, platf, ','.join(map(str,required_cores)))
errcnt = errcnt + 1
if not set(provided_cores).issubset(set(all_cores)):
if not quiet:
print "<b>Element targetConf</b>: Excess target images specified on Observer ID %s. Platform %s requires images for cores %s." %(obsid, platf, ','.join(map(str,required_cores)))
errcnt = errcnt + 1
#===========================================================================
# If there are still no errors, do additional test on the remaining elements:
#===========================================================================
if errcnt == 0:
# serialConf additional validation --------------------------------------
# * observer ids need to have a targetConf associated and must be unique
# * check baudrate depending on the operating system
# * check port depending on platform
# Check observer ids:
(ids, duplicates, allInList) = checkObsids(tree, '//d:serialConf/d:obsIds', ns, obsidlist)
if duplicates:
if not quiet:
print "<b>Element serialConf</b>: Some observer IDs have been used more than once."
errcnt = errcnt + 1
if not allInList:
if not quiet:
print "<b>Element serialConf</b>: Some observer IDs have been used but do not have a targetConf element associated with them."
errcnt = errcnt + 1
# Check baudrate (if specified) against operatingsystem for target:
srconfs = tree.xpath('//d:serialConf', namespaces=ns)
for srconf in srconfs:
obsids = srconf.xpath('d:obsIds', namespaces=ns)[0].text.split()
baudrate = srconf.xpath('d:baudrate', namespaces=ns)
if baudrate:
baudrate = int(srconf.xpath('d:baudrate', namespaces=ns)[0].text)
baudrate_line = srconf.xpath('d:baudrate', namespaces=ns)[0].sourceline
for obsid in obsids:
if obsiddict.has_key(obsid):
opersys = obsiddict[obsid].itervalues().next()[0]