Beispiel #1
0
def updateSites():

    global vo, dry, ceBdiiDict, onecore

    result = getSiteUpdates(vo, bdiiInfo=ceBdiiDict, onecore=onecore)
    if not result["OK"]:
        gLogger.error("Failed to get site updates", result["Message"])
        DIRACExit(-1)
    changeSet = result["Value"]

    updateCS(changeSet)
def updateSites():

    global vo, dry, ceBdiiDict

    result = getSiteUpdates(vo, bdiiInfo=ceBdiiDict)
    if not result['OK']:
        gLogger.error('Failed to get site updates', result['Message'])
        DIRACExit(-1)
    changeSet = result['Value']

    updateCS(changeSet)
def updateSEs():

  global vo, dry

  result = getSRMUpdates( vo )
  if not result['OK']:
    gLogger.error( 'Failed to get SRM updates', result['Message'] )
    DIRACExit( -1 )
  changeSet = result['Value']

  updateCS( changeSet )
Beispiel #4
0
def run():
    """
    Main function of the script
    """

    elements = getElements()
    if not elements["OK"]:
        subLogger.error(elements)
        DIRACExit(1)
    elements = elements["Value"]

    tabularPrint(elements)
def run():
    '''
    Main function of the script
  '''

    elements = getElements()
    if not elements['OK']:
        subLogger.error(elements)
        DIRACExit(1)
    elements = elements['Value']

    tabularPrint(elements)
Beispiel #6
0
def run():
    '''
    Main function of the script
  '''

    result = synchronize()
    if not result['OK']:
        subLogger.error(result['Message'])
        DIRACExit(1)

    if 'init' in switchDict:

        result = initSites()
        if not result['OK']:
            subLogger.error(result['Message'])
            DIRACExit(1)

        result = initSEs()
        if not result['OK']:
            subLogger.error(result['Message'])
            DIRACExit(1)
def main():
    Script.parseCommandLine()

    from DIRAC.Resources.Catalog.FileCatalog import FileCatalog

    import os
    args = Script.getPositionalArgs()

    if not len(args) >= 1:
        Script.showHelp(exitCode=1)
    else:
        inputFileName = args[0]
        catalogs = []
        if len(args) == 2:
            catalogs = [args[1]]

    if os.path.exists(inputFileName):
        inputFile = open(inputFileName, 'r')
        string = inputFile.read()
        lfns = string.splitlines()
        inputFile.close()
    else:
        lfns = [inputFileName]

    res = FileCatalog(catalogs=catalogs).getFileMetadata(lfns)
    if not res['OK']:
        print("ERROR:", res['Message'])
        DIRACExit(-1)

    print('FileName'.ljust(100), 'Size'.ljust(10), 'GUID'.ljust(40),
          'Status'.ljust(8), 'Checksum'.ljust(10))
    for lfn in sorted(res['Value']['Successful'].keys()):
        metadata = res['Value']['Successful'][lfn]
        checksum = ''
        if 'Checksum' in metadata:
            checksum = str(metadata['Checksum'])
        size = ''
        if 'Size' in metadata:
            size = str(metadata['Size'])
        guid = ''
        if 'GUID' in metadata:
            guid = str(metadata['GUID'])
        status = ''
        if 'Status' in metadata:
            status = str(metadata['Status'])
        print('%s %s %s %s %s' %
              (lfn.ljust(100), size.ljust(10), guid.ljust(40), status.ljust(8),
               checksum.ljust(10)))

    for lfn in sorted(res['Value']['Failed'].keys()):
        message = res['Value']['Failed'][lfn]
        print(lfn, message)
Beispiel #8
0
def initSites():
  '''
    Initializes Sites statuses taking their values from the "SiteMask" table of "JobDB" database.
  '''

  rssClient = ResourceStatusClient.ResourceStatusClient()

  sites = jobDB.getAllSiteMaskStatus()

  if not sites['OK']:
    subLogger.error(sites['Message'])
    DIRACExit(1)

  for site, elements in sites['Value'].iteritems():
    result = rssClient.addOrModifyStatusElement("Site", "Status",
                                                name=site, statusType='all', status=elements[0],
                                                elementType=site.split('.')[0], reason='dirac-rss-sync')
    if not result['OK']:
      subLogger.error(result['Message'])
      DIRACExit(1)

  return S_OK()
Beispiel #9
0
def main():
    Script.parseCommandLine(ignoreErrors=True)

    from DIRAC import gLogger, exit as DIRACExit
    from DIRAC.Interfaces.API.DiracAdmin import DiracAdmin

    diracAdmin = DiracAdmin()

    result = diracAdmin.getBannedSites()
    if result["OK"]:
        bannedSites = result["Value"]
    else:
        gLogger.error(result["Message"])
        DIRACExit(2)

    for site in bannedSites:
        result = diracAdmin.getSiteMaskLogging(site, printOutput=True)
        if not result["OK"]:
            gLogger.error(result["Message"])
            DIRACExit(2)

    DIRACExit(0)
Beispiel #10
0
def parseSwitches():
    '''
    Parses the arguments passed by the user
  '''

    Script.parseCommandLine(ignoreErrors=True)
    args = Script.getPositionalArgs()
    if args:
        subLogger.error(
            "Found the following positional args '%s', but we only accept switches"
            % args)
        subLogger.error("Please, check documentation below")
        Script.showHelp()
        DIRACExit(1)

    switches = dict(Script.getUnprocessedSwitches())
    # Default values
    switches.setdefault('elementType', None)
    switches.setdefault('name', None)
    switches.setdefault('tokenOwner', None)
    switches.setdefault('statusType', None)
    switches.setdefault('status', None)

    if not 'element' in switches:
        subLogger.error("element Switch missing")
        subLogger.error("Please, check documentation below")
        Script.showHelp()
        DIRACExit(1)

    if not switches['element'] in ('Site', 'Resource', 'Node'):
        subLogger.error("Found %s as element switch" % switches['element'])
        subLogger.error("Please, check documentation below")
        Script.showHelp()
        DIRACExit(1)

    subLogger.debug("The switches used are:")
    map(subLogger.debug, switches.iteritems())

    return switches
def main():
    # Registering arguments will automatically add their description to the help menu
    Script.registerArgument(("LocalFile: Path to local file containing LFNs",
                             "LFN:       Logical File Names"))
    Script.registerArgument(["Catalog:   file catalog plug-ins"],
                            mandatory=False)
    Script.parseCommandLine()

    from DIRAC.Resources.Catalog.FileCatalog import FileCatalog

    import os

    # parseCommandLine show help when mandatory arguments are not specified or incorrect argument
    inputFileName, catalogs = Script.getPositionalArgs(group=True)

    if os.path.exists(inputFileName):
        inputFile = open(inputFileName, "r")
        string = inputFile.read()
        lfns = string.splitlines()
        inputFile.close()
    else:
        lfns = [inputFileName]

    res = FileCatalog(catalogs=catalogs).getFileMetadata(lfns)
    if not res["OK"]:
        print("ERROR:", res["Message"])
        DIRACExit(-1)

    print("FileName".ljust(100), "Size".ljust(10), "GUID".ljust(40),
          "Status".ljust(8), "Checksum".ljust(10))
    for lfn in sorted(res["Value"]["Successful"].keys()):
        metadata = res["Value"]["Successful"][lfn]
        checksum = ""
        if "Checksum" in metadata:
            checksum = str(metadata["Checksum"])
        size = ""
        if "Size" in metadata:
            size = str(metadata["Size"])
        guid = ""
        if "GUID" in metadata:
            guid = str(metadata["GUID"])
        status = ""
        if "Status" in metadata:
            status = str(metadata["Status"])
        print("%s %s %s %s %s" %
              (lfn.ljust(100), size.ljust(10), guid.ljust(40), status.ljust(8),
               checksum.ljust(10)))

    for lfn in sorted(res["Value"]["Failed"].keys()):
        message = res["Value"]["Failed"][lfn]
        print(lfn, message)
Beispiel #12
0
def run():
    '''
    Main function of the script
  '''

    result = synchronize()
    if not result['OK']:
        subLogger.error(result['Message'])
        DIRACExit(1)

    if 'init' in switchDict:

        if switchDict.get('element') == "Site":
            result = initSites()
            if not result['OK']:
                subLogger.error(result['Message'])
                DIRACExit(1)

        if switchDict.get('element') == "Resource":
            result = initSEs()
            if not result['OK']:
                subLogger.error(result['Message'])
                DIRACExit(1)
Beispiel #13
0
def main():
    """
    This is the script main method, which will hold all the logic.
    """
    params = Params()

    # Script initialization
    Script.registerSwitches(params.switches)
    registerArguments()
    switchDict, repType, user, services = parseSwitchesAndPositionalArguments()

    # Import the required DIRAC modules
    from DIRAC.Interfaces.API.Dirac import Dirac

    # let's do something
    if services == "no elements":
        gLogger.error("No services defined")
        DIRACExit(1)
    gLogger.notice("Your %s is:" % ("DN" if user.startswith("/") else "name"), user)
    gLogger.notice("This is the servicesList:", ", ".join(services))
    gLogger.notice("We are done with %s report." % repType)

    DIRACExit(0)
Beispiel #14
0
def run():
    """
    Main function of the script
    """

    result = synchronize()
    if not result["OK"]:
        subLogger.error(result["Message"])
        DIRACExit(1)

    if "init" in switchDict:

        if switchDict.get("element") == "Site":
            result = initSites()
            if not result["OK"]:
                subLogger.error(result["Message"])
                DIRACExit(1)

        if switchDict.get("element") == "Resource":
            result = initSEs()
            if not result["OK"]:
                subLogger.error(result["Message"])
                DIRACExit(1)
Beispiel #15
0
def parseSwitches():
    """
  Parses the arguments passed by the user
  """

    Script.parseCommandLine(ignoreErrors=True)
    args = Script.getPositionalArgs()
    if args:
        subLogger.error(
            "Found the following positional args '%s', but we only accept switches"
            % args)
        subLogger.error("Please, check documentation below")
        Script.showHelp()
        DIRACExit(1)

    switches = dict(Script.getUnprocessedSwitches())
    switches.setdefault('statusType', None)
    switches.setdefault('releaseToken', False)

    for key in ('element', 'name', 'reason'):

        if key not in switches:
            subLogger.error("%s Switch missing" % key)
            subLogger.error("Please, check documentation below")
            Script.showHelp()
            DIRACExit(1)

    if not switches['element'] in ('Site', 'Resource', 'Node'):
        subLogger.error("Found %s as element switch" % switches['element'])
        subLogger.error("Please, check documentation below")
        Script.showHelp()
        DIRACExit(1)

    subLogger.debug("The switches used are:")
    map(subLogger.debug, switches.iteritems())

    return switches
def main():
    # Registering arguments will automatically add their description to the help menu
    Script.registerArgument(["User:     User name"])
    # parseCommandLine show help when mandatory arguments are not specified or incorrect argument
    _, args = Script.parseCommandLine(ignoreErrors=True)

    from DIRAC import exit as DIRACExit
    from DIRAC.Interfaces.API.DiracAdmin import DiracAdmin

    diracAdmin = DiracAdmin()
    exitCode = 0
    errorList = []

    choice = six.moves.input(
        "Are you sure you want to delete user/s %s? yes/no [no]: " %
        ", ".join(args))
    choice = choice.lower()
    if choice not in ("yes", "y"):
        print("Delete aborted")
        DIRACExit(0)

    for user in args:
        if not diracAdmin.csDeleteUser(user):
            errorList.append(("delete user", "Cannot delete user %s" % user))
            exitCode = 255

    if not exitCode:
        result = diracAdmin.csCommitChanges()
        if not result["OK"]:
            errorList.append(("commit", result["Message"]))
            exitCode = 255

    for error in errorList:
        print("ERROR %s: %s" % error)

    DIRACExit(exitCode)
Beispiel #17
0
def parseSwitches():
    '''
    Parses the arguments passed by the user
  '''

    Script.parseCommandLine(ignoreErrors=True)
    args = Script.getPositionalArgs()
    if args:
        subLogger.error(
            "Found the following positional args '%s', but we only accept switches"
            % args)
        subLogger.error("Please, check documentation below")
        Script.showHelp()
        DIRACExit(1)

    switches = dict(Script.getUnprocessedSwitches())

    for key in ('status', 'se', 'limit'):

        if not key in switches:
            print "You're not using switch --%s, query may take long!" % key

    if 'status' in switches.keys():
        if not switches['status'] in ('New', 'Offline', 'Waiting', 'Failed',
                                      'StageSubmitted', 'Staged'):
            subLogger.error(
                "Found \"%s\" as Status value. Incorrect value used!" %
                switches['status'])
            subLogger.error("Please, check documentation below")
            Script.showHelp()
            DIRACExit(1)

    subLogger.debug("The switches used are:")
    map(subLogger.debug, switches.iteritems())

    return switches
Beispiel #18
0
def initSites():
    '''
    Initializes Sites statuses taking their values from the "SiteMask" table of "JobDB" database.
  '''

    rssClient = ResourceStatusClient.ResourceStatusClient()

    sites = jobDB.getAllSiteMaskStatus()

    if not sites['OK']:
        subLogger.error(sites['Message'])
        DIRACExit(1)

    for site, elements in sites['Value'].iteritems():
        table = {'table': 'SiteStatus'}
        parameters = {
            'status': elements[0],
            'reason': 'Synchronized',
            'name': site,
            'dateEffective': elements[1],
            'tokenExpiration': Datetime,
            'elementType': 'Site',
            'statusType': 'all',
            'lastCheckTime': None,
            'tokenOwner': elements[2],
            'meta': table
        }

        result = rssClient.addIfNotThereStatusElement("Site", "Status",
                                                      **parameters)

        if not result['OK']:
            subLogger.error(result['Message'])
            DIRACExit(1)

    return S_OK()
def main():
    Script.parseCommandLine(ignoreErrors=True)
    args = Script.getPositionalArgs()

    from DIRAC import exit as DIRACExit
    from DIRAC.Interfaces.API.DiracAdmin import DiracAdmin
    diracAdmin = DiracAdmin()
    exitCode = 0
    errorList = []

    if len(args) < 1:
        Script.showHelp()

    choice = six.moves.input(
        "Are you sure you want to delete user/s %s? yes/no [no]: " %
        ", ".join(args))
    choice = choice.lower()
    if choice not in ("yes", "y"):
        print("Delete aborted")
        DIRACExit(0)

    for user in args:
        if not diracAdmin.csDeleteUser(user):
            errorList.append(("delete user", "Cannot delete user %s" % user))
            exitCode = 255

    if not exitCode:
        result = diracAdmin.csCommitChanges()
        if not result['OK']:
            errorList.append(("commit", result['Message']))
            exitCode = 255

    for error in errorList:
        print("ERROR %s: %s" % error)

    DIRACExit(exitCode)
Beispiel #20
0
def main():
    global subLogger
    global switchDict
    subLogger = gLogger.getSubLogger(__file__)

    # Script initialization
    registerSwitches()
    registerUsageMessage()
    switchDict = parseSwitches()

    # Run script
    run()

    # Bye
    DIRACExit(0)
Beispiel #21
0
def main():
    global subLogger
    global switchDict
    global DEFAULT_STATUS

    subLogger = gLogger.getSubLogger(__file__)
    registerSwitches()
    registerUsageMessage()
    switchDict = parseSwitches()
    DEFAULT_STATUS = switchDict.get("defaultStatus", "Banned")

    # Run script
    run()

    # Bye
    DIRACExit(0)
Beispiel #22
0
def main():
    # Registering arguments will automatically add their description to the help menu
    Script.registerArgument(("LocalFile: Path to local file containing LFNs",
                             "LFN:       Logical File Name"))
    Script.registerArgument(" SE:        Storage Element")
    Script.registerArgument(" status:    status")
    Script.parseCommandLine()

    from DIRAC.Resources.Catalog.FileCatalog import FileCatalog

    catalog = FileCatalog()
    import os

    # parseCommandLine show help when mandatory arguments are not specified or incorrect argument
    inputFileName, se, newStatus = Script.getPositionalArgs(group=True)

    if os.path.exists(inputFileName):
        inputFile = open(inputFileName, "r")
        string = inputFile.read()
        lfns = string.splitlines()
        inputFile.close()
    else:
        lfns = [inputFileName]

    res = catalog.getReplicas(lfns, True)
    if not res["OK"]:
        print(res["Message"])
        DIRACExit(-1)
    replicas = res["Value"]["Successful"]

    lfnDict = {}
    for lfn in lfns:
        lfnDict[lfn] = {}
        lfnDict[lfn]["SE"] = se
        lfnDict[lfn]["Status"] = newStatus
        lfnDict[lfn]["PFN"] = replicas[lfn][se]

    res = catalog.setReplicaStatus(lfnDict)
    if not res["OK"]:
        print("ERROR:", res["Message"])
    if res["Value"]["Failed"]:
        print("Failed to update %d replica status" %
              len(res["Value"]["Failed"]))
    if res["Value"]["Successful"]:
        print("Successfully updated %d replica status" %
              len(res["Value"]["Successful"]))
Beispiel #23
0
def main():
  global subLogger

  subLogger = gLogger.getSubLogger(__file__)

  # Script initialization
  registerSwitches()
  registerUsageMessage()
  args, switchDict = parseSwitches()

  # Unpack switchDict if 'name' or 'statusType' have multiple values
  switchDictSet = unpack(switchDict)

  # Run script
  run(args, switchDictSet)

  # Bye
  DIRACExit(0)
Beispiel #24
0
def main():
    global subLogger
    global registerUsageMessage

    subLogger = gLogger.getSubLogger(__file__)

    # Script initialization
    registerSwitches()
    registerUsageMessage()
    switchDict = parseSwitches()
    switchDictSets = unpack(switchDict)

    # Run script
    for switchDict in switchDictSets:
        run(switchDict)

    # Bye
    DIRACExit(0)
Beispiel #25
0
def printCEInfo(voName):

    resultQueues = Resources.getQueues(community=voName)
    if not resultQueues['OK']:
        gLogger.error('Failed to get CE information')
        DIRACExit(-1)

    fields = ("Site", 'CE', 'CEType', 'Queue', 'Status')
    records = []

    # get list of usable sites within this cycle
    resultMask = SiteStatus().getUsableSites()
    if not resultMask['OK']:
        return resultMask
    siteMaskList = resultMask.get('Value', [])

    rssClient = ResourceStatus()

    for site in resultQueues['Value']:
        siteStatus = "Active" if site in siteMaskList else "InActive"
        siteNew = True
        for ce in resultQueues['Value'][site]:

            ceStatus = siteStatus
            if rssClient.rssFlag:
                result = rssClient.getElementStatus(ce, "ComputingElement")
                if result['OK']:
                    ceStatus = result['Value'][ce]['all']

            ceNew = True
            for queue in resultQueues['Value'][site][ce]['Queues']:
                pSite = site if siteNew else ''
                pCE = ''
                ceType = ''
                if ceNew:
                    pCE = ce
                    ceType = resultQueues['Value'][site][ce]['CEType']
                records.append((pSite, pCE, ceType, queue, ceStatus))
                ceNew = False
                siteNew = False

    gLogger.notice(
        printTable(fields, records, printOut=False, columnSeparator='  '))
    return S_OK()
Beispiel #26
0
    def printCEInfo(voName):

        resultQueues = Resources.getQueues(community=voName)
        if not resultQueues["OK"]:
            gLogger.error("Failed to get CE information")
            DIRACExit(-1)

        fields = ("Site", "CE", "CEType", "Queue", "Status")
        records = []

        # get list of usable sites within this cycle
        resultMask = SiteStatus().getUsableSites()
        if not resultMask["OK"]:
            return resultMask
        siteMaskList = resultMask.get("Value", [])

        rssClient = ResourceStatus()

        for site in resultQueues["Value"]:
            siteStatus = "Active" if site in siteMaskList else "InActive"
            siteNew = True
            for ce in resultQueues["Value"][site]:

                ceStatus = siteStatus
                if rssClient.rssFlag:
                    result = rssClient.getElementStatus(ce, "ComputingElement")
                    if result["OK"]:
                        ceStatus = result["Value"][ce]["all"]

                ceNew = True
                for queue in resultQueues["Value"][site][ce]["Queues"]:
                    pSite = site if siteNew else ""
                    pCE = ""
                    ceType = ""
                    if ceNew:
                        pCE = ce
                        ceType = resultQueues["Value"][site][ce]["CEType"]
                    records.append((pSite, pCE, ceType, queue, ceStatus))
                    ceNew = False
                    siteNew = False

        gLogger.notice(
            printTable(fields, records, printOut=False, columnSeparator="  "))
        return S_OK()
def main():
  Script.parseCommandLine()

  from DIRAC.Resources.Catalog.FileCatalog import FileCatalog
  catalog = FileCatalog()
  import os
  args = Script.getPositionalArgs()
  if not len(args) == 3:
    Script.showHelp(exitCode=1)
  else:
    inputFileName = args[0]
    se = args[1]
    newStatus = args[2]

  if os.path.exists(inputFileName):
    inputFile = open(inputFileName, 'r')
    string = inputFile.read()
    lfns = string.splitlines()
    inputFile.close()
  else:
    lfns = [inputFileName]

  res = catalog.getReplicas(lfns, True)
  if not res['OK']:
    print(res['Message'])
    DIRACExit(-1)
  replicas = res['Value']['Successful']

  lfnDict = {}
  for lfn in lfns:
    lfnDict[lfn] = {}
    lfnDict[lfn]['SE'] = se
    lfnDict[lfn]['Status'] = newStatus
    lfnDict[lfn]['PFN'] = replicas[lfn][se]

  res = catalog.setReplicaStatus(lfnDict)
  if not res['OK']:
    print("ERROR:", res['Message'])
  if res['Value']['Failed']:
    print("Failed to update %d replica status" % len(res['Value']['Failed']))
  if res['Value']['Successful']:
    print("Successfully updated %d replica status" % len(res['Value']['Successful']))
Beispiel #28
0
def main():
    global subLogger
    global ResourceManagementClient

    subLogger = gLogger.getSubLogger(__file__)

    # Script initialization
    registerSwitches()
    registerUsageMessage()
    args, switchDict = parseSwitches()

    ResourceManagementClient = getattr(
        Utils.voimport("DIRAC.ResourceStatusSystem.Client.ResourceManagementClient"),
        "ResourceManagementClient",
    )

    # Run script
    run(args, switchDict)

    # Bye
    DIRACExit(0)
Beispiel #29
0
def main():
    global ceName
    global Queue
    global Site

    from DIRAC import gLogger, exit as DIRACExit
    from DIRAC.ConfigurationSystem.Client.Helpers import Resources

    def setCEName(args):
        global ceName
        ceName = args

    def setSite(args):
        global Site
        Site = args

    def setQueue(args):
        global Queue
        Queue = args

    Script.registerSwitch("N:", "Name=", "Computing Element Name (Mandatory)",
                          setCEName)
    Script.registerSwitch("S:", "Site=", "Site Name (Mandatory)", setSite)
    Script.registerSwitch("Q:", "Queue=", "Queue Name (Mandatory)", setQueue)

    Script.parseCommandLine(ignoreErrors=True)

    result = Resources.getQueue(Site, ceName, Queue)

    if not result["OK"]:
        # Normal DIRAC queue search failed, check for matching VM images
        vmresult = Resources.getVMTypeConfig(Site, ceName, Queue)
        if vmresult["OK"]:
            gLogger.notice(json.dumps(vmresult["Value"]))
            return
        # Queue & VM not found, return original queue failure message
        gLogger.error("Could not retrieve resource parameters",
                      ": " + vmresult["Message"])
        DIRACExit(1)
    gLogger.notice(json.dumps(result["Value"]))
Beispiel #30
0
def main():
    # Registering arguments will automatically add their description to the help menu
    Script.registerArgument(("LocalFile: Path to local file containing LFNs",
                             "LFN:       Logical File Name"))

    Script.parseCommandLine()

    # parseCommandLine show help when mandatory arguments are not specified or incorrect argument
    inputFileName = Script.getPositionalArgs(group=True)

    if os.path.exists(inputFileName):
        lfns = [
            lfn.strip().split()[0]
            for lfn in sorted(open(inputFileName, "r").read().splitlines())
        ]
    else:
        lfns = [inputFileName]

    from DIRAC.DataManagementSystem.Client.DataManager import DataManager

    dm = DataManager()
    retVal = 0
    for lfn in [lfn for lfn in lfns if lfn]:
        gLogger.notice("Cleaning directory %r ... " % lfn)
        result = dm.cleanLogicalDirectory(lfn)
        if not result["OK"]:
            gLogger.error("Failed to clean directory", result["Message"])
            retVal = -1
        else:
            if not result["Value"]["Failed"]:
                gLogger.notice("OK")
            else:
                for folder, message in result["Value"]["Failed"].items():
                    gLogger.error("Failed to clean folder",
                                  "%r: %s" % (folder, message))
                    retVal = -1

        DIRACExit(retVal)