Exemple #1
0
    def getVOUserData(self, vo, refreshFlag=False):
        """ Get a report for users of a given VO

    :param str vo: VO name
    :return: S_OK/S_ERROR, Value = user description dictionary
    """
        if refreshFlag:
            gConfig.forceRefresh()

        # Get DIRAC users
        diracUsers = getUsersInVO(vo)
        if not diracUsers:
            return S_ERROR("No VO users found for %s" % vo)

        if refreshFlag:
            result = self.csapi.downloadCSData()
            if not result['OK']:
                return result
        result = self.csapi.describeUsers(diracUsers)
        if not result['OK']:
            self.log.error('Could not retrieve CS User description')
        return result
Exemple #2
0
  def getVOUserData( self, vo, refreshFlag = False ):
    """ Get a report for users of a given VO

    :param str vo: VO name
    :return: S_OK/S_ERROR, Value = user description dictionary
    """
    if refreshFlag:
      gConfig.forceRefresh()

    # Get DIRAC users
    diracUsers = getUsersInVO( vo )
    if not diracUsers:
      return S_ERROR( "No VO users found for %s" % vo )

    if refreshFlag:
      result = self.csapi.downloadCSData()
      if not result['OK']:
        return result
    result = self.csapi.describeUsers( diracUsers )
    if not result['OK']:
      self.log.error( 'Could not retrieve CS User description' )
    return result
    def getVOUserData(self, refreshFlag=False):
        """Get a report for users of a given VO

        :param bool refreshFlag: flag to indicate that the configuration must be refreshed
                                 before looking up user data
        :return: S_OK/S_ERROR, Value = user description dictionary
        """
        if refreshFlag:
            gConfig.forceRefresh()

        # Get DIRAC users
        diracUsers = getUsersInVO(self.vo)
        if not diracUsers:
            return S_ERROR("No VO users found for %s" % self.vo)

        if refreshFlag:
            result = self.csapi.downloadCSData()
            if not result["OK"]:
                return result
        result = self.csapi.describeUsers(diracUsers)
        if not result["OK"]:
            self.log.error("Could not retrieve CS User description")
        return result
  def getVOUserData(self, refreshFlag=False):
    """ Get a report for users of a given VO

    :param bool refreshFlag: flag to indicate that the configuration must be refreshed
                             before looking up user data
    :return: S_OK/S_ERROR, Value = user description dictionary
    """
    if refreshFlag:
      gConfig.forceRefresh()

    # Get DIRAC users
    diracUsers = getUsersInVO(self.vo)
    if not diracUsers:
      return S_ERROR("No VO users found for %s" % self.vo)

    if refreshFlag:
      result = self.csapi.downloadCSData()
      if not result['OK']:
        return result
    result = self.csapi.describeUsers(diracUsers)
    if not result['OK']:
      self.log.error('Could not retrieve CS User description')
    return result
Exemple #5
0
    def __syncCSWithVOMS(self, vo):
        self.__adminMsgs = {'Errors': [], 'Info': []}

        # Get DIRAC group vs VOMS Role Mappings
        result = getVOMSRoleGroupMapping(vo)
        if not result['OK']:
            return result

        vomsDIRACMapping = result['Value']['VOMSDIRAC']
        diracVOMSMapping = result['Value']['DIRACVOMS']
        noVOMSGroups = result['Value']['NoVOMS']

        vomsSrv = VOMSService(vo)

        # Get VOMS VO name
        result = vomsSrv.admGetVOName()
        if not result['OK']:
            self.log.error('Could not retrieve VOMS VO name', "for %s" % vo)
            return result
        vomsVOName = result['Value'].lstrip('/')
        self.log.verbose("VOMS VO Name for %s is %s" % (vo, vomsVOName))

        # Get VOMS users
        result = vomsSrv.getUsers()
        if not result['OK']:
            self.log.error('Could not retrieve user information from VOMS',
                           result['Message'])
            return result
        vomsUserDict = result['Value']
        message = "There are %s registered users in VOMS VO %s" % (
            len(vomsUserDict), vomsVOName)
        self.__adminMsgs['Info'].append(message)
        self.log.info(message)

        # Get DIRAC users
        diracUsers = getUsersInVO(vo)
        if not diracUsers:
            return S_ERROR("No VO users found for %s" % vo)

        result = self.csapi.describeUsers(diracUsers)
        if not result['OK']:
            self.log.error('Could not retrieve CS User description')
            return result
        diracUserDict = result['Value']
        self.__adminMsgs['Info'].append(
            "There are %s registered users in DIRAC for VO %s" %
            (len(diracUserDict), vo))
        self.log.info("There are %s registered users in DIRAC VO %s" %
                      (len(diracUserDict), vo))

        # Find new and obsoleted user DNs
        existingDNs = []
        obsoletedDNs = []
        newDNs = []
        for user in diracUserDict:
            dn = diracUserDict[user]['DN']
            existingDNs.append(dn)
            if dn not in vomsUserDict:
                obsoletedDNs.append(dn)

        for dn in vomsUserDict:
            if dn not in existingDNs:
                newDNs.append(dn)

        allDiracUsers = getAllUsers()
        nonVOusers = list(set(allDiracUsers) - set(diracUsers))
        result = self.csapi.describeUsers(nonVOusers)
        if not result['OK']:
            self.log.error('Could not retrieve CS User description')
            return result
        nonVOUserDict = result['Value']

        # Process users
        defaultVOGroup = getVOOption(vo, "DefaultGroup", "%s_user" % vo)
        for dn in vomsUserDict:
            if dn in newDNs:
                # Find if the DN is already registered in the DIRAC CS
                diracName = ''
                for user in nonVOUserDict:
                    if dn == nonVOUserDict[user]['DN']:
                        diracName = user
                # We have a real new user
                if not diracName:
                    nickName = ''
                    result = vomsSrv.attGetUserNickname(
                        dn, vomsUserDict[dn]['CA'])
                    if result['OK']:
                        nickName = result['Value']

                    if nickName:
                        newDiracName = nickName
                    else:
                        newDiracName = getUserName(dn,
                                                   vomsUserDict[dn]['mail'])

                    ind = 1
                    trialName = newDiracName
                    while newDiracName in allDiracUsers:
                        # We have a user with the same name but with a different DN
                        newDiracName = "%s_%d" % (trialName, ind)
                        ind += 1

                    # We now have everything to add the new user
                    userDict = {
                        "DN": dn,
                        "CA": vomsUserDict[dn]['CA'],
                        "Email": vomsUserDict[dn]['mail']
                    }
                    groupsWithRole = []
                    for role in vomsUserDict[dn]['Roles']:
                        fullRole = "/%s/%s" % (vomsVOName, role)
                        group = vomsDIRACMapping.get(fullRole)
                        if group:
                            groupsWithRole.extend(group)
                    userDict['Groups'] = list(
                        set(groupsWithRole + [defaultVOGroup]))
                    self.__adminMsgs['Info'].append(
                        "Adding new user %s: %s" %
                        (newDiracName, str(userDict)))
                    self.voChanged = True
                    if self.autoAddUsers:
                        self.log.info("Adding new user %s: %s" %
                                      (newDiracName, str(userDict)))
                        result = self.csapi.modifyUser(
                            newDiracName, userDict, createIfNonExistant=True)
                        if not result['OK']:
                            self.log.warn('Failed adding new user %s' %
                                          newDiracName)
                    continue

                # We have an already existing user
                userDict = {
                    "DN": dn,
                    "CA": vomsUserDict[dn]['CA'],
                    "Email": vomsUserDict[dn]['mail']
                }
                nonVOGroups = nonVOUserDict.get(diracName,
                                                {}).get('Groups', [])
                existingGroups = diracUserDict.get(diracName,
                                                   {}).get('Groups', [])
                groupsWithRole = []
                for role in vomsUserDict[dn]['Roles']:
                    fullRole = "/%s/%s" % (vomsVOName, role)
                    group = vomsDIRACMapping.get(fullRole)
                    if group:
                        groupsWithRole.extend(group)
                keepGroups = nonVOGroups + groupsWithRole + [defaultVOGroup]
                for group in existingGroups:
                    role = diracVOMSMapping[group]
                    # Among already existing groups for the user keep those without a special VOMS Role
                    # because this membership is done by hand in the CS
                    if not "Role" in role:
                        keepGroups.append(group)
                    # Keep existing groups with no VOMS attribute if any
                    if group in noVOMSGroups:
                        keepGroups.append(group)
                userDict['Groups'] = keepGroups
                if self.autoModifyUsers:
                    result = self.csapi.modifyUser(diracName, userDict)
                    if result['OK'] and result['Value']:
                        self.voChanged = True

        # Check if there are potentially obsoleted users
        oldUsers = set()
        for user in diracUserDict:
            dn = diracUserDict[user]['DN']
            if not dn in vomsUserDict and not user in nonVOUserDict:
                for group in diracUserDict[user]['Groups']:
                    if not group in noVOMSGroups:
                        oldUsers.add(user)
        if oldUsers:
            self.voChanged = True
            self.__adminMsgs['Info'].append(
                'The following users to be checked for deletion: %s' %
                str(oldUsers))
            self.log.info(
                'The following users to be checked for deletion: %s' %
                str(oldUsers))

        return S_OK()
Exemple #6
0
  def __syncCSWithVOMS( self, vo ):
    self.__adminMsgs = { 'Errors' : [], 'Info' : [] }

    # Get DIRAC group vs VOMS Role Mappings
    result = getVOMSRoleGroupMapping( vo )
    if not result['OK']:
      return result

    vomsDIRACMapping = result['Value']['VOMSDIRAC']
    diracVOMSMapping = result['Value']['DIRACVOMS']
    noVOMSGroups = result['Value']['NoVOMS']

    vomsSrv = VOMSService( vo )

    # Get VOMS VO name
    result = vomsSrv.admGetVOName()
    if not result['OK']:
      self.log.error( 'Could not retrieve VOMS VO name', "for %s" % vo )
      return result
    vomsVOName = result[ 'Value' ].lstrip( '/' )
    self.log.verbose( "VOMS VO Name for %s is %s" % ( vo, vomsVOName ) )

    # Get VOMS users
    result = vomsSrv.getUsers()
    if not result['OK']:
      self.log.error( 'Could not retrieve user information from VOMS', result['Message'] )
      return result
    vomsUserDict = result[ 'Value' ]
    message = "There are %s registered users in VOMS VO %s" % ( len( vomsUserDict ), vomsVOName )
    self.__adminMsgs[ 'Info' ].append( message )
    self.log.info( message )

    # Get DIRAC users
    diracUsers = getUsersInVO( vo )
    if not diracUsers:
      return S_ERROR( "No VO users found for %s" % vo )

    result = self.csapi.describeUsers( diracUsers )
    if not result['OK']:
      self.log.error( 'Could not retrieve CS User description' )
      return result
    diracUserDict = result['Value']
    self.__adminMsgs[ 'Info' ].append( "There are %s registered users in DIRAC for VO %s" % ( len( diracUserDict ), vo ) )
    self.log.info( "There are %s registered users in DIRAC VO %s" % ( len( diracUserDict ), vo ) )

    # Find new and obsoleted user DNs
    existingDNs = []
    obsoletedDNs = []
    newDNs = []
    for user in diracUserDict:
      dn = diracUserDict[user]['DN']
      existingDNs.append( dn )
      if dn not in vomsUserDict:
        obsoletedDNs.append( dn )

    for dn in vomsUserDict:
      if dn not in existingDNs:
        newDNs.append( dn )

    allDiracUsers = getAllUsers()
    nonVOusers = list( set( allDiracUsers ) - set(diracUsers) )
    result = self.csapi.describeUsers( nonVOusers )
    if not result['OK']:
      self.log.error( 'Could not retrieve CS User description' )
      return result
    nonVOUserDict = result['Value']

    # Process users
    defaultVOGroup = getVOOption( vo, "DefaultGroup", "%s_user" % vo )
    for dn in vomsUserDict:
      if dn in newDNs:
        # Find if the DN is already registered in the DIRAC CS
        diracName = ''
        for user in nonVOUserDict:
          if dn == nonVOUserDict[user]['DN']:
            diracName = user
        # We have a real new user
        if not diracName:
          nickName = ''
          result = vomsSrv.attGetUserNickname( dn, vomsUserDict[dn]['CA'] )
          if result['OK']:
            nickName = result['Value']

          if nickName:
            newDiracName = nickName
          else:
            newDiracName = getUserName( dn, vomsUserDict[dn]['mail'] )

          ind = 1
          trialName = newDiracName
          while newDiracName in allDiracUsers:
            # We have a user with the same name but with a different DN
            newDiracName = "%s_%d" % ( trialName, ind )
            ind += 1

          # We now have everything to add the new user
          userDict = { "DN": dn, "CA": vomsUserDict[dn]['CA'], "Email": vomsUserDict[dn]['mail'] }
          groupsWithRole = []
          for role in vomsUserDict[dn]['Roles']:
            fullRole = "/%s/%s" % ( vomsVOName, role )
            group = vomsDIRACMapping.get( fullRole )
            if group:
              groupsWithRole.append( group )
          userDict['Groups'] = list( set( groupsWithRole + [defaultVOGroup] ) )
          self.__adminMsgs[ 'Info' ].append( "Adding new user %s: %s" % ( newDiracName, str( userDict ) ) )
          self.voChanged = True
          if self.autoAddUsers:
            self.log.info( "Adding new user %s: %s" % ( newDiracName, str( userDict ) ) )
            result = self.csapi.modifyUser( newDiracName, userDict, createIfNonExistant = True )
            if not result['OK']:
              self.log.warn( 'Failed adding new user %s' % newDiracName )
          continue

        # We have an already existing user
        userDict = { "DN": dn, "CA": vomsUserDict[dn]['CA'], "Email": vomsUserDict[dn]['mail'] }
        nonVOGroups = nonVOUserDict.get( diracName, {} ).get( 'Groups', [] )
        existingGroups = diracUserDict.get( diracName, {} ).get( 'Groups', [] )
        groupsWithRole = []
        for role in vomsUserDict[dn]['Roles']:
          fullRole = "/%s/%s" % ( vomsVOName, role )
          group = vomsDIRACMapping.get( fullRole )
          if group:
            groupsWithRole.append( group )
        keepGroups = nonVOGroups + groupsWithRole + [defaultVOGroup]
        for group in existingGroups:
          role = diracVOMSMapping[group]
          # Among already existing groups for the user keep those without a special VOMS Role
          # because this membership is done by hand in the CS
          if not "Role" in role:
            keepGroups.append( group )
          # Keep existing groups with no VOMS attribute if any
          if group in noVOMSGroups:
            keepGroups.append( group )
        userDict['Groups'] = keepGroups
        if self.autoModifyUsers:
          result = self.csapi.modifyUser( diracName, userDict )
          if result['OK'] and result['Value']:
            self.voChanged = True

    # Check if there are potentially obsoleted users
    oldUsers = set()
    for user in diracUserDict:
      dn = diracUserDict[user]['DN']
      if not dn in vomsUserDict and not user in nonVOUserDict:
        for group in diracUserDict[user]['Groups']:
          if not group in noVOMSGroups:
            oldUsers.add( user )
    if oldUsers:
      self.voChanged = True
      self.__adminMsgs[ 'Info' ].append( 'The following users to be checked for deletion: %s' % str( oldUsers ) )
      self.log.info( 'The following users to be checked for deletion: %s' % str( oldUsers ) )

    return S_OK()
    def executeForVO(self, vo):
        """
        Execute one SE and user synchronisation cycle for a VO.

        :param str vo: Virtual organisation name.
        :return: S_OK or S_ERROR
        :rtype: dict
        """

        valid_protocols = ["srm", "gsiftp", "davs", "https", "root"]
        default_email = None
        try:
            try:
                client = Client(account="root", auth_type="userpass")
            except Exception as err:
                self.log.info(
                    "Login to Rucio as root with password failed. Will try host cert/key",
                    str(err))
                certKeyTuple = Locations.getHostCertificateAndKeyLocation()
                if not certKeyTuple:
                    self.log.error("Hostcert/key location not set")
                    return S_ERROR("Hostcert/key location not set")
                hostcert, hostkey = certKeyTuple

                self.log.info("Logging in with a host cert/key pair:")
                self.log.debug("account: ",
                               self.clientConfig[vo]["privilegedAccount"])
                self.log.debug("rucio host: ",
                               self.clientConfig[vo]["rucioHost"])
                self.log.debug("auth  host: ",
                               self.clientConfig[vo]["authHost"])
                self.log.debug("CA cert path: ", self.caCertPath)
                self.log.debug("Cert location: ", hostcert)
                self.log.debug("Key location: ", hostkey)
                self.log.debug("VO: ", vo)

                client = Client(
                    account=self.clientConfig[vo]["privilegedAccount"],
                    rucio_host=self.clientConfig[vo]["rucioHost"],
                    auth_host=self.clientConfig[vo]["authHost"],
                    ca_cert=self.caCertPath,
                    auth_type="x509",
                    creds={
                        "client_cert": hostcert,
                        "client_key": hostkey
                    },
                    timeout=600,
                    user_agent="rucio-clients",
                    vo=vo,
                )

            self.log.info("Rucio client instantiated for VO:", vo)

            # Get the storage elements from Dirac Configuration and create them in Rucio
            newRSE = False
            self.log.info("Synchronizing SEs for VO ", vo)
            result = getStorageElements(vo)
            if result["OK"]:
                rses = [rse["rse"] for rse in client.list_rses()]
                for se in result["Value"]:
                    if se not in rses:
                        # The SE doesn't exist. Will create it
                        newRSE = True
                        self.log.info(
                            "Rucio Storage Element does not exist and will be created:",
                            se)
                        try:
                            client.add_rse(rse=se,
                                           deterministic=True,
                                           volatile=False)
                        except Exception as err:
                            self.log.error(
                                "Cannot create RSE",
                                "[RSE: %s, Error: %s]" % (se, str(err)))
                            continue

                        # Add RSE attributes for the new RSE
                        ret = gConfig.getOptionsDict(
                            "Resources/FTSEndpoints/FTS3")
                        ftsList = ""
                        if ret["OK"]:
                            ftsList = ",".join(ret["Value"].values())
                        dictRSEAttributes = {
                            "naming_convention": "BelleII",
                            "ANY": True,
                            "fts": ftsList
                        }
                        for key in dictRSEAttributes:
                            self.log.info(
                                "Setting RSE attributes",
                                "[RSE: %s, Attr. name: %s, Value: %s]" %
                                (se, key, dictRSEAttributes[key]),
                            )
                            client.add_rse_attribute(
                                se, key, value=dictRSEAttributes[key])
                        client.set_local_account_limit("root", se,
                                                       100000000000000000)

                    # Create the protocols
                    try:
                        protocols = client.get_protocols(se)
                    except RSEProtocolNotSupported as err:
                        self.log.info("Cannot get protocols for",
                                      "[RSE %s, Error: %s]" % (se, str(err)))
                        protocols = []
                    existing_protocols = []
                    for prot in protocols:
                        existing_protocols.append(
                            (str(prot["scheme"]), str(prot["hostname"]),
                             str(prot["port"]), str(prot["prefix"])))
                    protocols_to_create = []
                    for params in result["Value"][se]:
                        prot = (
                            str(params["scheme"]),
                            str(params["hostname"]),
                            str(params["port"]),
                            str(params["prefix"]),
                        )
                        protocols_to_create.append(prot)
                        if prot not in existing_protocols and prot[
                                0] in valid_protocols:
                            # The protocol defined in Dirac does not exist in Rucio. Will be created
                            self.log.info(
                                "Will create new protocol:",
                                "%s://%s:%s%s on %s" %
                                (params["scheme"], params["hostname"],
                                 params["port"], params["prefix"], se),
                            )
                            try:
                                client.add_protocol(rse=se, params=params)
                            except Duplicate as err:
                                self.log.info(
                                    "Protocol already exists on",
                                    "[RSE: %s, schema:%s]" %
                                    (se, params["scheme"]))
                            except Exception as err:
                                self.log.error(
                                    "Cannot create protocol on RSE",
                                    "[RSE: %s, Error: %s]" % (se, str(err)))
                        else:
                            update = False
                            for protocol in protocols:
                                if prot == (
                                        str(protocol["scheme"]),
                                        str(protocol["hostname"]),
                                        str(protocol["port"]),
                                        str(protocol["prefix"]),
                                ):
                                    # Check if the protocol defined in Dirac has the same priority as the one defined in Rucio
                                    for domain in ["lan", "wan"]:
                                        for activity in [
                                                "read", "write", "delete"
                                        ]:
                                            if (params["domains"][domain]
                                                [activity] !=
                                                    protocol["domains"][domain]
                                                [activity]):
                                                update = True
                                                break

                                    if (params["domains"]["wan"]
                                        ["third_party_copy"] !=
                                            protocol["domains"]["wan"]
                                        ["third_party_copy"]):
                                        update = True
                                    if update:
                                        data = {
                                            "prefix":
                                            params["prefix"],
                                            "read_lan":
                                            params["domains"]["lan"]["read"],
                                            "read_wan":
                                            params["domains"]["wan"]["read"],
                                            "write_lan":
                                            params["domains"]["lan"]["write"],
                                            "write_wan":
                                            params["domains"]["wan"]["write"],
                                            "delete_lan":
                                            params["domains"]["lan"]["delete"],
                                            "delete_wan":
                                            params["domains"]["wan"]["delete"],
                                            "third_party_copy":
                                            params["domains"]["wan"]["write"],
                                        }
                                        self.log.info(
                                            "Will update protocol:",
                                            "%s://%s:%s%s on %s" % (
                                                params["scheme"],
                                                params["hostname"],
                                                params["port"],
                                                params["prefix"],
                                                se,
                                            ),
                                        )
                                        client.update_protocols(
                                            rse=se,
                                            scheme=params["scheme"],
                                            data=data,
                                            hostname=params["hostname"],
                                            port=params["port"],
                                        )
                    for prot in existing_protocols:
                        if prot not in protocols_to_create:
                            self.log.info(
                                "Will delete protocol:", "%s://%s:%s%s on %s" %
                                (prot[0], prot[1], prot[2], prot[3], se))
                            client.delete_protocols(se,
                                                    scheme=prot[0],
                                                    hostname=prot[1],
                                                    port=prot[2])
            else:
                self.log.error("Cannot get SEs:", result["Message"])

            # If new RSE added, add distances
            rses = [rse["rse"] for rse in client.list_rses()]
            if newRSE:
                self.log.info("Adding distances")
                for src_rse, dest_rse in permutations(rses, r=2):
                    try:
                        client.add_distance(src_rse, dest_rse, {
                            "ranking": 1,
                            "distance": 10
                        })
                    except Exception as err:
                        self.log.error(
                            "Cannot add distance for",
                            "Source RSE: %s, Dest RSE: %s, Error:%s" %
                            (src_rse, dest_rse, str(err)),
                        )

            # Collect the shares from Dirac Configuration and create them in Rucio
            self.log.info("Synchronizing shares")
            result = Operations().getOptionsDict("Production/SEshares")
            if result["OK"]:
                rseDict = result["Value"]
                for rse in rses:
                    try:
                        self.log.info("Setting productionSEshare for",
                                      "[RSE: %s : Share: %s", rse,
                                      rseDict.get(rse, 0))
                        client.add_rse_attribute(rse, "productionSEshare",
                                                 rseDict.get(rse, 0))
                    except Exception as err:
                        self.log.error(
                            "Cannot create productionSEshare for RSE:", rse)
            else:
                self.log.error("Cannot get SEs", result["Message"])

            result = Operations().getSections("Shares")
            if result["OK"]:
                for dataLevel in result["Value"]:
                    result = Operations().getOptionsDict("Shares/%s" %
                                                         dataLevel)
                    if not result["OK"]:
                        self.log.error("Cannot get SEs:" % result["Message"])
                        continue
                    rseDict = result["Value"]
                    for rse in rses:
                        try:
                            self.log.info(
                                "Setting", "%sShare for %s : %s" %
                                (dataLevel, rse, rseDict.get(rse, 0)))
                            client.add_rse_attribute(rse,
                                                     "%sShare" % dataLevel,
                                                     rseDict.get(rse, 0))
                        except Exception as err:
                            self.log.error("Cannot create share:",
                                           "%sShare for %s", dataLevel, rse)
            else:
                self.log.error("Cannot get shares:", result["Message"])

            # Create the RSE attribute PrimaryDataSE and OccupancyLFN
            result = gConfig.getValue(
                "Resources/StorageElementGroups/PrimarySEs")
            result = getStorageElements(vo)
            if result["OK"]:
                allSEs = result["Value"]
                primarySEs = resolveSEGroup("PrimarySEs", allSEs)
                self.log.info("Will set primarySEs flag to:", str(primarySEs))
                for rse in rses:
                    if rse in allSEs:
                        storage = StorageElement(rse)
                        if not storage.valid:
                            self.log.warn(
                                "Storage element is not valid. Skipped RSE:",
                                rse)
                            continue
                        occupancyLFN = storage.options.get("OccupancyLFN")
                        try:
                            client.add_rse_attribute(rse, "OccupancyLFN",
                                                     occupancyLFN)
                        except Exception as err:
                            self.log.error(
                                "Cannot create RSE attribute OccupancyLFN for",
                                "[RSE: %s, Error: %s]" % (rse, str(err)))
                    if rse in primarySEs:
                        try:
                            client.add_rse_attribute(rse, "PrimaryDataSE",
                                                     True)
                        except Exception as err:
                            self.log.error(
                                "Cannot create RSE attribute PrimaryDataSE for",
                                "[RSE: %s, Error: %s]" % (rse, str(err)),
                            )
                    else:
                        try:
                            client.delete_rse_attribute(rse, "PrimaryDataSE")
                        except RSEAttributeNotFound:
                            pass
                        except Exception as err:
                            self.log.error(
                                "Cannot remove RSE attribute PrimaryDataSE for",
                                "[RSE: %s, Error: %s]" % (rse, str(err)),
                            )
            self.log.info("RSEs synchronized for VO: ", vo)

            # Collect the user accounts from Dirac Configuration and create user accounts in Rucio
            self.log.info("Synchronizing accounts for VO", vo)
            listAccounts = [
                str(acc["account"]) for acc in client.list_accounts()
            ]
            listScopes = [str(scope) for scope in client.list_scopes()]
            dnMapping = {}
            diracUsers = getUsersInVO(vo)
            self.log.debug(" Will consider following Dirac users for",
                           "[VO: %s, Dirac users: %s]" % (vo, diracUsers))

            for account in diracUsers:
                dn = getUserOption(account, "DN")
                email = getUserOption(account, "Email")
                dnMapping[dn] = email
                if account not in listAccounts:
                    self.log.info("Will create account with associated DN ",
                                  "[account: %s, DN: %s]" % (account, dn))
                    try:
                        client.add_account(account, "USER", email)
                        listAccounts.append(account)
                    except Exception as err:
                        self.log.error(
                            "Cannot create account",
                            "[account: %s, Error: %s]" % (account, str(err)))
                    try:
                        client.add_identity(account=account,
                                            identity=dn,
                                            authtype="X509",
                                            email=email,
                                            default=True)
                    except Exception as err:
                        self.log.error(
                            "Cannot add identity for account",
                            "[Identity: dn=%s,  account:%s, Error: %s]" %
                            (dn, account, str(err)),
                        )
                        self.log.error(
                            " Account/identity skipped (it will not be created in Rucio)",
                            "[%s/%s]" % (account, dn))
                        continue
                    for rse in rses:
                        client.set_local_account_limit(account, rse,
                                                       1000000000000000)
                else:
                    try:
                        client.add_identity(account=account,
                                            identity=dn,
                                            authtype="X509",
                                            email=email,
                                            default=True)
                    except Duplicate:
                        pass
                    except Exception as err:
                        self.log.error(
                            "Cannot create identity for account",
                            "[DN: %s, account: %s, Error: %s]" %
                            (dn, account, str(err)),
                        )
                scope = "user." + account
                if scope not in listScopes:
                    try:
                        self.log.info("Will create a scope",
                                      "[Scope:  %s]" % scope)
                        client.add_scope(account, scope)
                        self.log.info("Scope successfully added",
                                      "[Scope:  %s]" % scope)
                    except Exception as err:
                        self.log.error(
                            "Cannot create a scope",
                            "[Scope: %s, Error: %s]" % (scope, str(err)))

            # Collect the group accounts from Dirac Configuration and create service accounts in Rucio
            result = getGroupsForVO(vo)
            if result["OK"]:
                groups = result["Value"]
                self.log.debug(" Will consider following Dirac groups for",
                               "[%s VO: %s]" % (vo, groups))
            else:
                groups = []
                self.log.debug("No Dirac groups for", "%s VO " % vo)
                self.log.debug("No Rucio service accounts will be created")
            for group in groups:
                if group not in listAccounts:
                    self.log.info(
                        "Will create SERVICE account for Dirac group:",
                        str(group))
                    try:
                        client.add_account(group, "SERVICE", None)
                        listAccounts.append(group)
                    except Exception as err:
                        self.log.error(
                            "Cannot create SERVICE account for",
                            "[group: %s, Error: %s]" % (group, str(err)))
                    for rse in rses:
                        client.set_local_account_limit(account, rse,
                                                       1000000000000000)

                for dn in getDNsInGroup(group):
                    try:
                        client.add_identity(account=group,
                                            identity=dn,
                                            authtype="X509",
                                            email=dnMapping.get(
                                                dn, default_email))
                    except Duplicate:
                        pass
                    except Exception as err:
                        self.log.error(
                            "Cannot create identity for account",
                            "[identity %s, account %s, Error: %s]" %
                            (dn, group, str(err)),
                        )
                        self.log.error(format_exc())

            # Collect the group accounts from Dirac Configuration and create service accounts in Rucio
            result = getHosts()
            if not result["OK"]:
                self.log.error("Cannot get host accounts:",
                               "%s" % result["Message"])
            else:
                hosts = result["Value"]
                for host in hosts:
                    dn = getHostOption(host, "DN")
                    email = dnMapping.get(dn, default_email)
                    try:
                        client.add_identity(account="dirac_srv",
                                            identity=dn,
                                            authtype="X509",
                                            email=email)
                    except Duplicate:
                        pass
                    except Exception as err:
                        self.log.error(
                            "Cannot create identity for account dirac_srv:",
                            "[DN: %s, Error: %s]" % (dn, str(err)))
                        self.log.error(format_exc())

            return S_OK()
        except Exception as exc:
            self.log.exception("Synchronisation for VO failed. VO skipped ",
                               "VO=%s" % vo,
                               lException=exc)
            return S_ERROR(str(format_exc()))