Skip to content

Commit

Permalink
feat: store in TransformationDB the Author alongside the AuthorDN
Browse files Browse the repository at this point in the history
  • Loading branch information
fstagni committed Jul 26, 2023
1 parent 506eadc commit 649274a
Show file tree
Hide file tree
Showing 14 changed files with 80 additions and 170 deletions.
8 changes: 3 additions & 5 deletions src/DIRAC/TransformationSystem/Agent/TaskManagerAgentBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def __init__(self, *args, **kwargs):
# credentials
self.shifterProxy = None
self.credentials = None
self.credTuple = (None, None, None)
self.credTuple = (None, None)

self.pluginLocation = ""
self.bulkSubmissionFlag = False
Expand Down Expand Up @@ -101,17 +101,16 @@ def execute(self):
"""The execution method is transformations that need to be processed"""

# 1. determining which credentials will be used for the submission
owner, ownerGroup, ownerDN = None, None, None
owner, ownerGroup = None, None
# getting the credentials for submission
resProxy = getProxyInfo(proxy=False, disableVOMS=False)
if resProxy["OK"]: # there is a shifterProxy
proxyInfo = resProxy["Value"]
owner = proxyInfo["username"]
ownerGroup = proxyInfo["group"]
ownerDN = proxyInfo["identity"]
self.log.info(f"ShifterProxy: Tasks will be submitted with the credentials {owner}:{ownerGroup}")
elif self.credentials:
owner, ownerGroup, ownerDN = self.credTuple
owner, ownerGroup = self.credTuple
else:
self.log.info("Using per Transformation Credentials!")

Expand All @@ -137,7 +136,6 @@ def execute(self):
transformations,
owner=owner,
ownerGroup=ownerGroup,
ownerDN=ownerDN,
)

# 2.2. Determine whether the task files status is to be monitored and updated
Expand Down
20 changes: 10 additions & 10 deletions src/DIRAC/TransformationSystem/Agent/TransformationCleaningAgent.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ def execute(self):
self._executeClean(transDict)
else:
self.log.info(
f"Cleaning transformation {transDict['TransformationID']} with {transDict['AuthorDN']}, {transDict['AuthorGroup']}"
f"Cleaning transformation {transDict['TransformationID']} with {transDict['Author']}, {transDict['AuthorGroup']}"
)
executeWithUserProxy(self._executeClean)(
transDict, proxyUserDN=transDict["AuthorDN"], proxyUserGroup=transDict["AuthorGroup"]
transDict, proxyUserName=transDict["Author"], proxyUserGroup=transDict["AuthorGroup"]
)
else:
self.log.error("Failed to get transformations", res["Message"])
Expand All @@ -164,11 +164,11 @@ def execute(self):
self._executeRemoval(transDict)
else:
self.log.info(
"Removing files for transformation %(TransformationID)s with %(AuthorDN)s, %(AuthorGroup)s"
"Removing files for transformation %(TransformationID)s with %(Author)s, %(AuthorGroup)s"
% transDict
)
executeWithUserProxy(self._executeRemoval)(
transDict, proxyUserDN=transDict["AuthorDN"], proxyUserGroup=transDict["AuthorGroup"]
transDict, proxyUserName=transDict["Author"], proxyUserGroup=transDict["AuthorGroup"]
)
else:
self.log.error("Could not get the transformations", res["Message"])
Expand All @@ -186,11 +186,11 @@ def execute(self):
self._executeArchive(transDict)
else:
self.log.info(
"Archiving files for transformation %(TransformationID)s with %(AuthorDN)s, %(AuthorGroup)s"
"Archiving files for transformation %(TransformationID)s with %(Author)s, %(AuthorGroup)s"
% transDict
)
executeWithUserProxy(self._executeArchive)(
transDict, proxyUserDN=transDict["AuthorDN"], proxyUserGroup=transDict["AuthorGroup"]
transDict, proxyUserName=transDict["Author"], proxyUserGroup=transDict["AuthorGroup"]
)
else:
self.log.error("Could not get the transformations", res["Message"])
Expand Down Expand Up @@ -244,22 +244,22 @@ def finalize(self):
self._executeClean(transDict)
else:
self.log.info(
f"Cleaning transformation {transDict['TransformationID']} with {transDict['AuthorDN']}, {transDict['AuthorGroup']}"
f"Cleaning transformation {transDict['TransformationID']} with {transDict['Author']}, {transDict['AuthorGroup']}"
)
executeWithUserProxy(self._executeClean)(
transDict, proxyUserDN=transDict["AuthorDN"], proxyUserGroup=transDict["AuthorGroup"]
transDict, proxyUserName=transDict["Author"], proxyUserGroup=transDict["AuthorGroup"]
)

for transDict in toArchive:
if self.shifterProxy:
self._executeArchive(transDict)
else:
self.log.info(
"Archiving files for transformation %(TransformationID)s with %(AuthorDN)s, %(AuthorGroup)s"
"Archiving files for transformation %(TransformationID)s with %(Author)s, %(AuthorGroup)s"
% transDict
)
executeWithUserProxy(self._executeArchive)(
transDict, proxyUserDN=transDict["AuthorDN"], proxyUserGroup=transDict["AuthorGroup"]
transDict, proxyUser=transDict["Author"], proxyUserGroup=transDict["AuthorGroup"]
)

# Remove JobIDs that were unknown to the TransformationSystem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,8 @@ def test_checkReservedTasks(
"TransformationID": 1,
"Operations": ["op1", "op2"],
"Body": "veryBigBody",
"Owner": "prodMan",
"OwnerDN": "/ca=man/user=prodMan",
"OwnerGroup": "prodMans",
"Owner": "prod",
"OwnerGroup": "prods",
}
sOkJobDict = {"OK": True, "Value": {"JobDictionary": {123: "foo", 456: "bar"}}}
sOkJobs = {"OK": True, "Value": {123: "foo", 456: "bar"}}
Expand Down
1 change: 0 additions & 1 deletion src/DIRAC/TransformationSystem/Client/RequestTasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from DIRAC import S_OK, S_ERROR, gLogger

from DIRAC.ConfigurationSystem.Client.Helpers.Registry import getDNForUsername
from DIRAC.Core.Security.ProxyInfo import getProxyInfo
from DIRAC.Core.Utilities.JEncode import decode

Expand Down
53 changes: 4 additions & 49 deletions src/DIRAC/TransformationSystem/Client/Transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from DIRAC.TransformationSystem.Client.BodyPlugin.BaseBody import BaseBody
from DIRAC.TransformationSystem.Client.TransformationClient import TransformationClient
from DIRAC.ConfigurationSystem.Client.Helpers.Operations import Operations
from DIRAC.Core.Security.ProxyInfo import getProxyInfo
from DIRAC.RequestManagementSystem.Client.Operation import Operation

COMPONENT_NAME = "Transformation"
Expand Down Expand Up @@ -269,7 +268,7 @@ def getTransformationLogging(self, printOutput=False):
loggingList = res["Value"]
if printOutput:
self._printFormattedDictList(
loggingList, ["Message", "MessageDate", "AuthorDN"], "MessageDate", "MessageDate"
loggingList, ["Message", "MessageDate", "Author"], "MessageDate", "MessageDate"
)
return S_OK(loggingList)

Expand Down Expand Up @@ -425,63 +424,19 @@ def getTransformations(
self._printFormattedDictList(res["Value"], outputFields, "TransformationID", orderBy)
return res

#############################################################################
def getAuthorDNfromProxy(self):
"""gets the AuthorDN and username of the transformation from the uploaded proxy"""
username = ""
author = ""
res = getProxyInfo()
if res["OK"]:
author = res["Value"]["identity"]
username = res["Value"]["username"]
else:
gLogger.error(f"Unable to get uploaded proxy Info {res['Message']} ")
return S_ERROR(res["Message"])

res = {"username": username, "authorDN": author}
return S_OK(res)

#############################################################################
def getTransformationsByUser(
self,
authorDN="",
userName="",
transID=[],
transStatus=[],
outputFields=["TransformationID", "Status", "AgentType", "TransformationName", "CreationDate", "AuthorDN"],
outputFields=["TransformationID", "Status", "AgentType", "TransformationName", "CreationDate", "Author"],
orderBy="TransformationID",
printOutput=False,
):
condDict = {}
if authorDN == "":
res = self.getAuthorDNfromProxy()
if not res["OK"]:
gLogger.error(res["Message"])
return S_ERROR(res["Message"])
else:
foundUserName = res["Value"]["username"]
foundAuthor = res["Value"]["authorDN"]
# If the username whom created the uploaded proxy is different than the provided username report error and exit
if not (userName == "" or userName == foundUserName):
gLogger.error(
"Couldn't resolve the authorDN for user '%s' from the uploaded proxy (proxy created by '%s')"
% (userName, foundUserName)
)
return S_ERROR(
"Couldn't resolve the authorDN for user '%s' from the uploaded proxy (proxy created by '%s')"
% (userName, foundUserName)
)

userName = foundUserName
authorDN = foundAuthor
gLogger.info(
"Will list transformations created by user '%s' with status '%s'"
% (userName, ", ".join(transStatus))
)
else:
gLogger.info(f"Will list transformations created by '{authorDN}' with status '{', '.join(transStatus)}'")

condDict["AuthorDN"] = authorDN
gLogger.info(f"Will list transformations created by user '{userName}' with status '{transStatus}'")
condDict["Author"] = userName
if transID:
condDict["TransformationID"] = transID
if transStatus:
Expand Down
41 changes: 5 additions & 36 deletions src/DIRAC/TransformationSystem/Client/TransformationCLI.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,53 +112,22 @@ def do_getall(self, args):
def do_getAllByUser(self, args):
"""Get all transformations created by a given user
The first argument is the authorDN or username. The authorDN
is preferred: it need to be inside quotes because contains
white spaces. Only authorDN should be quoted.
The first argument is the username.
When the username is provided instead,
the authorDN is retrieved from the uploaded proxy,
so that the retrieved transformations are those created by
the user who uploaded that proxy: that user could be different
that the username provided to the function.
usage: getAllByUser authorDN or username [Status] [Status]
usage: getAllByUser username [Status] [Status]
"""
oTrans = Transformation()
argss = args.split()
username = ""
author = ""
status = []
if not len(argss) > 0:
print(self.do_getAllByUser.__doc__)
return

# if the user didnt quoted the authorDN ends
if "=" in argss[0] and argss[0][0] not in ["'", '"']:
print("AuthorDN need to be quoted (just quote that argument)")
return
username = argss[0]
status = argss[1:]

if argss[0][0] in ["'", '"']: # authorDN given
author = argss[0]
status_idx = 1
for arg in argss[1:]:
author += " " + arg
status_idx += 1
if arg[-1] in ["'", '"']:
break
# At this point we should have something like 'author'
if not author[0] in ["'", '"'] or not author[-1] in ["'", '"']:
print("AuthorDN need to be quoted (just quote that argument)")
return
else:
author = author[1:-1] # throw away the quotes
# the rest are the requested status
status = argss[status_idx:]
else: # username given
username = argss[0]
status = argss[1:]

oTrans.getTransformationsByUser(authorDN=author, userName=username, transStatus=status, printOutput=True)
oTrans.getTransformationsByUser(userName=username, transStatus=status, printOutput=True)

def do_summaryTransformations(self, args):
"""Show the summary for a list of Transformations
Expand Down
28 changes: 14 additions & 14 deletions src/DIRAC/TransformationSystem/DB/TransformationDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def __init__(self, dbname=None, dbconfig=None, dbIn=None, parentLogger=None):
"LongDescription",
"CreationDate",
"LastUpdate",
"AuthorDN",
"Author",
"AuthorGroup",
"Type",
"Plugin",
Expand Down Expand Up @@ -129,7 +129,7 @@ def addTransformation(
transName,
description,
longDescription,
authorDN,
author,
authorGroup,
transType,
plugin,
Expand Down Expand Up @@ -162,7 +162,7 @@ def addTransformation(
body = res["Value"]
req = (
"INSERT INTO Transformations (TransformationName,Description,LongDescription, \
CreationDate,LastUpdate,AuthorDN,AuthorGroup,Type,Plugin,AgentType,\
CreationDate,LastUpdate,Author,AuthorGroup,Type,Plugin,AgentType,\
FileMask,Status,TransformationGroup,GroupSize,\
InheritedFrom,Body,MaxNumberOfTasks,EventsPerTask)\
VALUES ('%s','%s','%s',\
Expand All @@ -173,7 +173,7 @@ def addTransformation(
transName,
description,
longDescription,
authorDN,
author,
authorGroup,
transType,
plugin,
Expand Down Expand Up @@ -218,19 +218,19 @@ def addTransformation(
originalID = res["Value"]
# FIXME: this is not the right place to change status information, and in general the whole should not be here
res = self.setTransformationParameter(
originalID, "Status", "Completing", author=authorDN, connection=connection
originalID, "Status", "Completing", author=author, connection=connection
)
if not res["OK"]:
gLogger.error("Failed to update parent transformation status: now deleting", res["Message"])
return self.deleteTransformation(transID, connection=connection)
res = self.setTransformationParameter(
originalID, "AgentType", "Automatic", author=authorDN, connection=connection
originalID, "AgentType", "Automatic", author=author, connection=connection
)
if not res["OK"]:
gLogger.error("Failed to update parent transformation agent type, now deleting", res["Message"])
return self.deleteTransformation(transID, connection=connection)
message = "Creation of the derived transformation (%d)" % transID
self.__updateTransformationLogging(originalID, message, authorDN, connection=connection)
self.__updateTransformationLogging(originalID, message, author, connection=connection)
res = self.getTransformationFiles(condDict={"TransformationID": originalID}, connection=connection)
if not res["OK"]:
gLogger.error("Could not get transformation files, now deleting", res["Message"])
Expand Down Expand Up @@ -266,7 +266,7 @@ def addTransformation(
gLogger.error("Failed to add files to transformation", f"{transID} {res['Message']}")
message = "Created transformation %d" % transID

self.__updateTransformationLogging(transID, message, authorDN, connection=connection)
self.__updateTransformationLogging(transID, message, author, connection=connection)
return S_OK(transID)

def getTransformations(
Expand Down Expand Up @@ -1268,19 +1268,19 @@ def __deleteTransformationTaskInputs(self, transID, taskID=0, connection=False):
# These methods manipulate the TransformationLog table
#

def __updateTransformationLogging(self, transName, message, authorDN, connection=False):
def __updateTransformationLogging(self, transName, message, author, connection=False):
"""Update the Transformation log table with any modifications"""
if not authorDN:
if not author:
res = getProxyInfo(False, False)
if res["OK"]:
authorDN = res["Value"]["subject"]
author = res["Value"]["username"]
res = self._getConnectionTransID(connection, transName)
if not res["OK"]:
return res
connection = res["Value"]["Connection"]
transID = res["Value"]["TransformationID"]
req = "INSERT INTO TransformationLog (TransformationID,Message,Author,MessageDate)"
req = req + f" VALUES ({transID},'{message}','{authorDN}',UTC_TIMESTAMP());"
req = req + f" VALUES ({transID},'{message}','{author}',UTC_TIMESTAMP());"
return self._update(req, conn=connection)

def getTransformationLogging(self, transName, connection=False):
Expand All @@ -1296,11 +1296,11 @@ def getTransformationLogging(self, transName, connection=False):
if not res["OK"]:
return res
transList = []
for transID, message, authorDN, messageDate in res["Value"]:
for transID, message, author, messageDate in res["Value"]:
transDict = {}
transDict["TransformationID"] = transID
transDict["Message"] = message
transDict["AuthorDN"] = authorDN
transDict["Author"] = author
transDict["MessageDate"] = messageDate
transList.append(transDict)
return S_OK(transList)
Expand Down
3 changes: 2 additions & 1 deletion src/DIRAC/TransformationSystem/DB/TransformationDB.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ CREATE TABLE Transformations(
LongDescription TEXT,
CreationDate DATETIME,
LastUpdate DATETIME,
Author VARCHAR(255) NOT NULL,
AuthorDN VARCHAR(255) NOT NULL,
AuthorGroup VARCHAR(255) NOT NULL,
Type CHAR(32) DEFAULT 'Simulation',
Plugin CHAR(32) DEFAULT 'None',
AgentType CHAR(32) DEFAULT 'Manual',
Status CHAR(32) DEFAULT 'New',
Status CHAR(32) DEFAULT 'New',
FileMask VARCHAR(255),
TransformationGroup varchar(255) NOT NULL default 'General',
TransformationFamily varchar(64) default '0',
Expand Down
Loading

0 comments on commit 649274a

Please sign in to comment.