Skip to content

Commit

Permalink
Add setter methods map to WMWorkload and call it for all reqArg param…
Browse files Browse the repository at this point in the history
…eters
  • Loading branch information
Todor Trendafilov Ivanov authored and todor-ivanov committed Sep 17, 2024
1 parent d339b4a commit 0bb4dc9
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 20 deletions.
52 changes: 32 additions & 20 deletions src/python/WMCore/ReqMgr/Service/Request.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,27 +424,39 @@ def _handleNoStatusUpdate(self, workload, request_args, dn):
cherrypy.log('Updated workqueue statistics of "{}", with: {}'.format(workload.name(), reqArgs))
return report

reqArgsNothandled = []
for reqArg in reqArgs:
if reqArg == 'RequestPriority':
validate_request_priority(reqArgs)
# must update three places: GQ elements, workload_cache and workload spec
self.gq_service.updatePriority(workload.name(), reqArgs['RequestPriority'])
workload.setPriority(reqArgs['RequestPriority'])
cherrypy.log('Updated priority of "{}" to: {}'.format(workload.name(), reqArgs['RequestPriority']))
elif reqArg == "SiteWhitelist":
workload.setSiteWhitelist(reqArgs["SiteWhitelist"])
cherrypy.log('Updated SiteWhitelist of "{}", with: {}'.format(workload.name(), reqArgs['SiteWhitelist']))
elif reqArg == "SiteBlacklist":
workload.setSiteBlacklist(reqArgs["SiteBlacklist"])
cherrypy.log('Updated SiteBlacklist of "{}", with: {}'.format(workload.name(), reqArgs['SiteBlacklist']))
else:
reqArgsNothandled.append(reqArg)
cherrypy.log("Unhandled argument for no-status update: %s" % reqArg)
# reqArgsNothandled = []
# for reqArg in reqArgs:
# if reqArg == 'RequestPriority':
# validate_request_priority(reqArgs)
# # must update three places: GQ elements, workload_cache and workload spec
# self.gq_service.updatePriority(workload.name(), reqArgs['RequestPriority'])
# workload.setPriority(reqArgs['RequestPriority'])
# cherrypy.log('Updated priority of "{}" to: {}'.format(workload.name(), reqArgs['RequestPriority']))
# elif reqArg == "SiteWhitelist":
# workload.setSiteWhitelist(reqArgs["SiteWhitelist"])
# cherrypy.log('Updated SiteWhitelist of "{}", with: {}'.format(workload.name(), reqArgs['SiteWhitelist']))
# elif reqArg == "SiteBlacklist":
# workload.setSiteBlacklist(reqArgs["SiteBlacklist"])
# cherrypy.log('Updated SiteBlacklist of "{}", with: {}'.format(workload.name(), reqArgs['SiteBlacklist']))
# else:
# reqArgsNothandled.append(reqArg)
# cherrypy.log("Unhandled argument for no-status update: %s" % reqArg)

# TODO: map setters to key names:
# Creating a setter method map - directly in the workload object.

# Update all workload parameters based on the full reqArgsDiff dictionary
workload.updateWorkloadArgs(reqArgsDiff)

if reqArgsNothandled:
msg = "There were unhandled arguments left for no-status update: %s" % reqArgsNothandled
raise InvalidSpecParameterValue(msg)
# Commit the changes of the current workload object to the database:
workload.saveCouchUrl(workload.specUrl())

# Commit all Global WorkQueue changes per workflow in a single go:
# self.gq_service.updateElementsByWorkflow(workload.name(), reqArgsDiff)

# if reqArgsNothandled:
# msg = "There were unhandled arguments left for no-status update: %s" % reqArgsNothandled
# raise InvalidSpecParameterValue(msg)

# Commit the changes of the current workload object to the database:
workload.saveCouchUrl(workload.specUrl())
Expand Down
51 changes: 51 additions & 0 deletions src/python/WMCore/WMSpec/WMWorkload.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

from builtins import next, range
from future.utils import viewitems, viewvalues
from inspect import signature
from collections import namedtuple
import inspect

from Utils.Utilities import strToBool
from WMCore.Configuration import ConfigSection
Expand Down Expand Up @@ -59,6 +62,8 @@ class WMWorkloadException(WMException):
pass


setterTuple = namedtuple('SetterTuple', ['reqArg', 'setterFunc', 'setterSignature'])

class WMWorkloadHelper(PersistencyHelper):
"""
_WMWorkloadHelper_
Expand All @@ -68,6 +73,52 @@ class WMWorkloadHelper(PersistencyHelper):

def __init__(self, wmWorkload=None):
self.data = wmWorkload
self.settersMap = {}

def updateWorkloadArgs(self, reqArgs):
"""
Method to take a dictionary of arguments of the type:
{reqArg1: value,
reqArg2: value,
...}
and update the workload by a predefined map of reqArg to setter methods.
:param reqArgs: A Dictionary of request arguments to be updated
:return: Nothing, Raises an error of type WMWorkloadException if
fails to apply the proper setter method
"""
# NOTE: So far we support only a single argument setter methods, like
# setSiteWhitelist or setPriority. This may change in the future,
# but it will require a change in the logic of how we validate and
# call the proper setter methods bellow.

# populate the current instance settersMap
self.settersMap['RequestPriority'] = setterTuple('RequestPriority', self.setPriority, inspect.signature(self.setPriority))
self.settersMap['SiteBlacklist'] = setterTuple('SiteBlacklist', self.setSiteBlacklist, inspect.signature(self.setSiteBlacklist))
self.settersMap['SiteWhitelist'] = setterTuple('SiteWhitelist', self.setSiteWhitelist, inspect.signature(self.setSiteWhitelist))

# First validate if we can properly call the setter function given the reqArgs passed.
for reqArg, argValue in reqArgs.items():
if not self.settersMap.get(reqArg, None):
msg = f"Unsupported or missing setter method for updating reqArg: {reqArg}."
raise WMWorkloadException(msg)
try:
self.settersMap[reqArg].setterSignature.bind(argValue)
except TypeError as ex:
msg = f"Setter's method signature does not match the method calls we currently support: Error: req{str(ex)}"
raise WMWorkloadException(msg)

# Now go through the reqArg again and call every setter method according to the map
for reqArg, argValue in reqArgs.items():
try:
self.settersMap[reqArg].setterFunc(argValue)
except Exception as ex:
currFrame = inspect.currentframe()
argsInfo = inspect.getargvalues(currFrame)
argVals = {arg: argsInfo.locals.get(arg) for arg in argsInfo.args}
msg = f"Failure while calling setter method {self.settersMap[reqArg].setterFunc.__name__} "
msg += f"With arguments: {argVals}"
msg += f"Full exception string: {str(ex)}"
raise WMWorkloadException(msg)

def setSpecUrl(self, url):
self.data.persistency.specUrl = sanitizeURL(url)["url"]
Expand Down

0 comments on commit 0bb4dc9

Please sign in to comment.