Beispiel #1
0
  def __discoverCredentialsToUse(self):
    """ Discovers which credentials to use for connection.
        * Server certificate:
          -> If KW_USE_CERTIFICATES in kwargs, sets it in self.__useCertificates
          ->If not, check gConfig.useServerCertificate(), and sets it in self.__useCertificates and kwargs[KW_USE_CERTIFICATES]
        * Certification Authorities check:
           -> if KW_SKIP_CA_CHECK is not in kwargs and we are using the certificates, set KW_SKIP_CA_CHECK to false in kwargs
           -> if KW_SKIP_CA_CHECK is not in kwargs and we are not using the certificate, check the CS.skipCACheck
        * Proxy Chain
           -> if KW_PROXY_CHAIN in kwargs, we remove it and dump its string form into kwargs[KW_PROXY_STRING]

    """
    # Use certificates?
    if self.KW_USE_CERTIFICATES in self.kwargs:
      self.__useCertificates = self.kwargs[self.KW_USE_CERTIFICATES]
    else:
      self.__useCertificates = gConfig.useServerCertificate()
      self.kwargs[self.KW_USE_CERTIFICATES] = self.__useCertificates
    if self.KW_SKIP_CA_CHECK not in self.kwargs:
      if self.__useCertificates:
        self.kwargs[self.KW_SKIP_CA_CHECK] = False
      else:
        self.kwargs[self.KW_SKIP_CA_CHECK] = CS.skipCACheck()
    if self.KW_PROXY_CHAIN in self.kwargs:
      try:
        self.kwargs[self.KW_PROXY_STRING] = self.kwargs[self.KW_PROXY_CHAIN].dumpAllToString()['Value']
        del self.kwargs[self.KW_PROXY_CHAIN]
      except BaseException:
        return S_ERROR("Invalid proxy chain specified on instantiation")
    return S_OK()
Beispiel #2
0
  def __discoverCredentialsToUse( self ):
    """ Discovers which credentials to use for connection.
        * Server certificate:
          -> If KW_USE_CERTIFICATES in kwargs, sets it in self.__useCertificates
          ->If not, check gConfig.useServerCertificate(), and sets it in self.__useCertificates and kwargs[KW_USE_CERTIFICATES]
        * Certification Authorities check:
           -> if KW_SKIP_CA_CHECK is not in kwargs and we are using the certificates, set KW_SKIP_CA_CHECK to false in kwargs
           -> if KW_SKIP_CA_CHECK is not in kwargs and we are not using the certificate, check the CS.skipCACheck
        * Proxy Chain
           -> if KW_PROXY_CHAIN in kwargs, we remove it and dump its string form into kwargs[KW_PROXY_STRING]

    """
    #Use certificates?
    if self.KW_USE_CERTIFICATES in self.kwargs:
      self.__useCertificates = self.kwargs[ self.KW_USE_CERTIFICATES ]
    else:
      self.__useCertificates = gConfig.useServerCertificate()
      self.kwargs[ self.KW_USE_CERTIFICATES ] = self.__useCertificates
    if self.KW_SKIP_CA_CHECK not in self.kwargs:
      if self.__useCertificates:
        self.kwargs[ self.KW_SKIP_CA_CHECK ] = False
      else:
        self.kwargs[ self.KW_SKIP_CA_CHECK ] = CS.skipCACheck()
    if self.KW_PROXY_CHAIN in self.kwargs:
      try:
        self.kwargs[ self.KW_PROXY_STRING ] = self.kwargs[ self.KW_PROXY_CHAIN ].dumpAllToString()[ 'Value' ]
        del self.kwargs[ self.KW_PROXY_CHAIN ]
      except:
        return S_ERROR( "Invalid proxy chain specified on instantiation" )
    return S_OK()
 def connect( self ):
   errorMsg = ""
   for res in socket.getaddrinfo( self.host, self.port, 0,
                                 socket.SOCK_STREAM ):
     _af, _socktype, _proto, _canonname, addTuple = res
     result = gSSLSocketFactory.createClientSocket( addTuple, useCertificates = gConfig.useServerCertificate() )
     if not result[ 'OK' ]:
       errorMsg = result[ 'Message' ]
       continue
     self.sock = result[ 'Value' ]
     break
   if not self.sock:
     raise socket.error, errorMsg
Beispiel #4
0
 def connect(self):
     errorMsg = ""
     for res in socket.getaddrinfo(self.host, self.port, 0,
                                   socket.SOCK_STREAM):
         _af, _socktype, _proto, _canonname, addTuple = res
         result = gSSLSocketFactory.createClientSocket(
             addTuple, useCertificates=gConfig.useServerCertificate())
         if not result['OK']:
             errorMsg = result['Message']
             continue
         self.sock = result['Value']
         break
     if not self.sock:
         raise socket.error, errorMsg
Beispiel #5
0
 def __discoverCredentialsToUse( self ):
   #Use certificates?
   if self.KW_USE_CERTIFICATES in self.kwargs:
     self.useCertificates = self.kwargs[ self.KW_USE_CERTIFICATES ]
   else:
     self.useCertificates = gConfig.useServerCertificate()
     self.kwargs[ self.KW_USE_CERTIFICATES ] = self.useCertificates
   if self.KW_SKIP_CA_CHECK not in self.kwargs:
     if self.useCertificates:
       self.kwargs[ self.KW_SKIP_CA_CHECK ] = False
     else:
       self.kwargs[ self.KW_SKIP_CA_CHECK ] = CS.skipCACheck()
   if self.KW_PROXY_CHAIN in self.kwargs:
     try:
       self.kwargs[ self.KW_PROXY_STRING ] = self.kwargs[ self.KW_PROXY_CHAIN ].dumpAllToString()[ 'Value' ]
       del self.kwargs[ self.KW_PROXY_CHAIN ]
     except:
       return S_ERROR( "Invalid proxy chain specified on instantiation" )
   return S_OK()
Beispiel #6
0
    def __discoverCredentialsToUse(self):
        """ Discovers which credentials to use for connection.
        * Server certificate:
          -> If KW_USE_CERTIFICATES in kwargs, sets it in self.__useCertificates
          -> If not, check gConfig.useServerCertificate(), and sets it in self.__useCertificates
              and kwargs[KW_USE_CERTIFICATES]
        * Certification Authorities check:
           -> if KW_SKIP_CA_CHECK is not in kwargs and we are using the certificates,
                set KW_SKIP_CA_CHECK to false in kwargs
           -> if KW_SKIP_CA_CHECK is not in kwargs and we are not using the certificate, check the skipCACheck
        * Proxy Chain

        WARNING: MOSTLY COPY/PASTE FROM Core/Diset/private/BaseClient

    """
        # Use certificates?
        if self.KW_USE_CERTIFICATES in self.kwargs:
            self.__useCertificates = self.kwargs[self.KW_USE_CERTIFICATES]
        else:
            self.__useCertificates = gConfig.useServerCertificate()
            self.kwargs[self.KW_USE_CERTIFICATES] = self.__useCertificates
        if self.KW_SKIP_CA_CHECK not in self.kwargs:
            if self.__useCertificates:
                self.kwargs[self.KW_SKIP_CA_CHECK] = False
            else:
                self.kwargs[self.KW_SKIP_CA_CHECK] = skipCACheck()

        # Rewrite a little bit from here: don't need the proxy string, we use the file
        if self.KW_PROXY_CHAIN in self.kwargs:
            try:
                self.kwargs[self.KW_PROXY_STRING] = self.kwargs[
                    self.KW_PROXY_CHAIN].dumpAllToString()['Value']
                del self.kwargs[self.KW_PROXY_CHAIN]
            except BaseException:
                return S_ERROR(
                    "Invalid proxy chain specified on instantiation")

        # ==== REWRITED FROM HERE ====

        # For certs always check CA's. For clients skipServerIdentityCheck

        return S_OK()
Beispiel #7
0
 def __discoverCredentialsToUse(self):
     #Use certificates?
     if self.KW_USE_CERTIFICATES in self.kwargs:
         self.useCertificates = self.kwargs[self.KW_USE_CERTIFICATES]
     else:
         self.useCertificates = gConfig.useServerCertificate()
         self.kwargs[self.KW_USE_CERTIFICATES] = self.useCertificates
     if self.KW_SKIP_CA_CHECK not in self.kwargs:
         if self.useCertificates:
             self.kwargs[self.KW_SKIP_CA_CHECK] = False
         else:
             self.kwargs[self.KW_SKIP_CA_CHECK] = CS.skipCACheck()
     if self.KW_PROXY_CHAIN in self.kwargs:
         try:
             self.kwargs[self.KW_PROXY_STRING] = self.kwargs[
                 self.KW_PROXY_CHAIN].dumpAllToString()['Value']
             del self.kwargs[self.KW_PROXY_CHAIN]
         except:
             return S_ERROR(
                 "Invalid proxy chain specified on instantiation")
     return S_OK()
Beispiel #8
0
  def _connect(self):
    """ Establish the connection.
        It uses the URL discovered in __discoverURL.
        In case the connection cannot be established, __discoverURL
        is called again, and _connect calls itself.
        We stop after trying self.__nbOfRetry * self.__nbOfUrls

        :return: S_OK()/S_ERROR()
    """
    # Check if the useServerCertificate configuration changed
    # Note: I am not really sure that  all this block makes
    # any sense at all since all these variables are
    # evaluated in __discoverCredentialsToUse
    if gConfig.useServerCertificate() != self.__useCertificates:
      if self.__forceUseCertificates is None:
        self.__useCertificates = gConfig.useServerCertificate()
        self.kwargs[self.KW_USE_CERTIFICATES] = self.__useCertificates
        # The server certificate use context changed, rechecking the transport sanity
        result = self.__checkTransportSanity()
        if not result['OK']:
          return result

    # Take all the extra credentials
    self.__discoverExtraCredentials()
    if not self.__initStatus['OK']:
      return self.__initStatus
    if self.__enableThreadCheck:
      self.__checkThreadID()

    gLogger.debug("Trying to connect to: %s" % self.serviceURL)
    try:
      # Calls the transport method of the apropriate protocol.
      # self.__URLTuple[1:3] = [server name, port, System/Component]
      transport = gProtocolDict[self.__URLTuple[0]]['transport'](self.__URLTuple[1:3], **self.kwargs)
      # the socket timeout is the default value which is 1.
      # later we increase to 5
      retVal = transport.initAsClient()
      # We try at most __nbOfRetry each URLs
      if not retVal['OK']:
        gLogger.warn("Issue getting socket:", "%s : %s : %s" % (transport, self.__URLTuple, retVal['Message']))
        # We try at most __nbOfRetry each URLs
        if self.__retry < self.__nbOfRetry * self.__nbOfUrls - 1:
          # Recompose the URL (why not using self.serviceURL ? )
          url = "%s://%s:%d/%s" % (self.__URLTuple[0], self.__URLTuple[1], int(self.__URLTuple[2]), self.__URLTuple[3])
          # Add the url to the list of banned URLs if it is not already there. (Can it happen ? I don't think so)
          if url not in self.__bannedUrls:
            gLogger.warn("Non-responding URL temporarily banned", "%s" % url)
            self.__bannedUrls += [url]
          # Increment the retry counter
          self.__retry += 1
          # 16.07.20 CHRIS: I guess this setSocketTimeout does not behave as expected.
          # If the initasClient did not work, we anyway re-enter the whole method,
          # so a new transport object is created.
          # However, it migh be that this timeout value was propagated down to the
          # SocketInfoFactory singleton, and thus used, but that means that the timeout
          # specified in parameter was then void.

          # If it is our last attempt for each URL, we increase the timeout
          if self.__retryCounter == self.__nbOfRetry - 1:
            transport.setSocketTimeout(5)  # we increase the socket timeout in case the network is not good
          gLogger.info("Retry connection", ": %d to %s" % (self.__retry, self.serviceURL))
          # If we tried all the URL, we increase the global counter (__retryCounter), and sleep
          if len(self.__bannedUrls) == self.__nbOfUrls:
            self.__retryCounter += 1
            # we run only one service! In that case we increase the retry delay.
            self.__retryDelay = 3. / self.__nbOfUrls if self.__nbOfUrls > 1 else 2
            gLogger.info("Waiting %f seconds before retry all service(s)" % self.__retryDelay)
            time.sleep(self.__retryDelay)
          # rediscover the URL
          self.__discoverURL()
          # try to reconnect
          return self._connect()
        else:
          return retVal
    except Exception as e:
      gLogger.exception(lException=True, lExcInfo=True)
      return S_ERROR("Can't connect to %s: %s" % (self.serviceURL, repr(e)))
    # We add the connection to the transport pool
    gLogger.debug("Connected to: %s" % self.serviceURL)
    trid = getGlobalTransportPool().add(transport)

    return S_OK((trid, transport))
Beispiel #9
0
    def __discoverCredentialsToUse(self):
        """Discovers which credentials to use for connection.
        * Server certificate:
          -> If KW_USE_CERTIFICATES in kwargs, sets it in self.__useCertificates
          -> If not, check gConfig.useServerCertificate(), and sets it in self.__useCertificates
              and kwargs[KW_USE_CERTIFICATES]
        * Certification Authorities check:
           -> if KW_SKIP_CA_CHECK is not in kwargs and we are using the certificates,
                set KW_SKIP_CA_CHECK to false in kwargs
           -> if KW_SKIP_CA_CHECK is not in kwargs and we are not using the certificate, check the skipCACheck
        * Bearer token:
          -> If KW_USE_ACCESS_TOKEN in kwargs, sets it in self.__useAccessToken
          -> If not, check "/DIRAC/Security/UseTokens", and sets it in self.__useAccessToken
              and kwargs[KW_USE_ACCESS_TOKEN]
          -> If not, check 'DIRAC_USE_ACCESS_TOKEN' in os.environ, sets it in self.__useAccessToken
              and kwargs[KW_USE_ACCESS_TOKEN]
        * Proxy Chain

        WARNING: MOSTLY COPY/PASTE FROM Core/Diset/private/BaseClient

        """
        # Use certificates?
        if self.KW_USE_CERTIFICATES in self.kwargs:
            self.__useCertificates = self.kwargs[self.KW_USE_CERTIFICATES]
        else:
            self.__useCertificates = gConfig.useServerCertificate()
            self.kwargs[self.KW_USE_CERTIFICATES] = self.__useCertificates
        if self.KW_SKIP_CA_CHECK not in self.kwargs:
            if self.__useCertificates:
                self.kwargs[self.KW_SKIP_CA_CHECK] = False
            else:
                self.kwargs[self.KW_SKIP_CA_CHECK] = skipCACheck()

        # Use tokens?
        if self.KW_USE_ACCESS_TOKEN in self.kwargs:
            self.__useAccessToken = self.kwargs[self.KW_USE_ACCESS_TOKEN]
        elif "DIRAC_USE_ACCESS_TOKEN" in os.environ:
            self.__useAccessToken = os.environ.get("DIRAC_USE_ACCESS_TOKEN",
                                                   "false").lower() in ("y",
                                                                        "yes",
                                                                        "true")
        else:
            self.__useAccessToken = gConfig.getValue(
                "/DIRAC/Security/UseTokens", "false").lower() in (
                    "y",
                    "yes",
                    "true",
                )
        self.kwargs[self.KW_USE_ACCESS_TOKEN] = self.__useAccessToken

        if self.__useAccessToken:
            from DIRAC.Resources.IdProvider.IdProviderFactory import IdProviderFactory

            result = IdProviderFactory().getIdProvider("DIRACCLI")
            if not result["OK"]:
                return result
            self.__idp = result["Value"]

        # Rewrite a little bit from here: don't need the proxy string, we use the file
        if self.KW_PROXY_CHAIN in self.kwargs:
            try:
                self.kwargs[self.KW_PROXY_STRING] = self.kwargs[
                    self.KW_PROXY_CHAIN].dumpAllToString()["Value"]
                del self.kwargs[self.KW_PROXY_CHAIN]
            except Exception:
                return S_ERROR(
                    "Invalid proxy chain specified on instantiation")

        # ==== REWRITED FROM HERE ====

        # For certs always check CA's. For clients skipServerIdentityCheck

        return S_OK()
Beispiel #10
0
  def __call__( self ):
    """ generic function to process one Request of a type requestType

    This method could be run in a thread.

    :param self: self reference
    :param str requestType: request type 
    :return: S_OK/S_ERROR
    """
    self.always("executing request %s" % self.requestName )

    ################################################################
    ## get ownerDN and ownerGroup
    ownerDN = self.requestObj.getAttribute( "OwnerDN" )
    if not ownerDN["OK"]:
      return ownerDN
    ownerDN = ownerDN["Value"]
    ownerGroup = self.requestObj.getAttribute( "OwnerGroup" )
    if not ownerGroup["OK"]:
      return ownerGroup
    ownerGroup = ownerGroup["Value"]
    
    ## save request owner
    self.requestOwnerDN = ownerDN if ownerDN else ""
    self.requestOwnerGroup = ownerGroup if ownerGroup else ""

    #################################################################
    ## change proxy
    ownerProxyFile = None
    if ownerDN and ownerGroup:
      ownerProxyFile = self.changeProxy( ownerDN, ownerGroup )
      if not ownerProxyFile["OK"]:
        self.error( "handleReuqest: unable to get proxy for '%s'@'%s': %s" % ( ownerDN, 
                                                                               ownerGroup, 
                                                                               ownerProxyFile["Message"] ) )
        update = self.putBackRequest( self.requestName, self.requestString )
        if not update["OK"]:
          self.error( "handleRequest: error when updating request: %s" % update["Message"] )
          return update
        return ownerProxyFile
      ownerProxyFile = ownerProxyFile["Value"]
      #self.ownerProxyFile = ownerProxyFile
      self.info( "Will execute request for '%s'@'%s' using proxy file %s" % ( ownerDN, ownerGroup, ownerProxyFile ) )
    else:
      self.info( "Will execute request for DataManager using her/his proxy")

    #################################################################
    ## execute handlers
    ret = { "OK" : False, "Message" : "" }
    useServerCert = gConfig.useServerCertificate()
    try:
      # Execute task with the owner proxy even for contacting DIRAC services
      if useServerCert:
        gConfigurationData.setOptionInCFG('/DIRAC/Security/UseServerCertificate','false')
      ret = self.handleRequest()
    finally:
      if useServerCert:
        gConfigurationData.setOptionInCFG('/DIRAC/Security/UseServerCertificate','true') 
      ## delete owner proxy
      if self.__dataManagerProxy:
        os.environ["X509_USER_PROXY"] = self.__dataManagerProxy
        if ownerProxyFile and os.path.exists( ownerProxyFile ):
          os.unlink( ownerProxyFile )
    if not ret["OK"]:
      self.error( "handleRequest: error during request processing: %s" % ret["Message"] )
      self.error( "handleRequest: will put original request back" )
      update = self.putBackRequest( self.requestName, self.requestString )
      if not update["OK"]:
        self.error( "handleRequest: error when putting back request: %s" % update["Message"] )
    ## return at least
    return ret
Beispiel #11
0
  def __call__( self ):
    """ generic function to process one Request of a type requestType

    This method could be run in a thread.

    :param self: self reference
    :param str requestType: request type 
    :return: S_OK/S_ERROR
    """
    self.always("executing request %s" % self.requestName )

    ################################################################
    ## get ownerDN and ownerGroup
    ownerDN = self.requestObj.getAttribute( "OwnerDN" )
    if not ownerDN["OK"]:
      return ownerDN
    ownerDN = ownerDN["Value"]
    ownerGroup = self.requestObj.getAttribute( "OwnerGroup" )
    if not ownerGroup["OK"]:
      return ownerGroup
    ownerGroup = ownerGroup["Value"]
    
    ## save request owner
    self.requestOwnerDN = ownerDN if ownerDN else ""
    self.requestOwnerGroup = ownerGroup if ownerGroup else ""

    #################################################################
    ## change proxy
    ownerProxyFile = None
    if ownerDN and ownerGroup:
      ownerProxyFile = self.changeProxy( ownerDN, ownerGroup )
      if not ownerProxyFile["OK"]:
        self.error( "handleReuqest: unable to get proxy for '%s'@'%s': %s" % ( ownerDN, 
                                                                               ownerGroup, 
                                                                               ownerProxyFile["Message"] ) )
        update = self.putBackRequest( self.requestName, self.requestString )
        if not update["OK"]:
          self.error( "handleRequest: error when updating request: %s" % update["Message"] )
          return update
        return ownerProxyFile
      ownerProxyFile = ownerProxyFile["Value"]
      #self.ownerProxyFile = ownerProxyFile
      self.info( "Will execute request for '%s'@'%s' using proxy file %s" % ( ownerDN, ownerGroup, ownerProxyFile ) )
    else:
      self.info( "Will execute request for DataManager using her/his proxy")

    #################################################################
    ## execute handlers
    ret = { "OK" : False, "Message" : "" }
    useServerCert = gConfig.useServerCertificate()
    try:
      # Execute task with the owner proxy even for contacting DIRAC services
      if useServerCert:
        gConfigurationData.setOptionInCFG('/DIRAC/Security/UseServerCertificate','false')
      ret = self.handleRequest()
    finally:
      if useServerCert:
        gConfigurationData.setOptionInCFG('/DIRAC/Security/UseServerCertificate','true') 
      ## delete owner proxy
      if self.__dataManagerProxy:
        os.environ["X509_USER_PROXY"] = self.__dataManagerProxy
        if ownerProxyFile and os.path.exists( ownerProxyFile ):
          os.unlink( ownerProxyFile )
    if not ret["OK"]:
      self.error( "handleRequest: error during request processing: %s" % ret["Message"] )
      self.error( "handleRequest: will put original request back" )
      update = self.putBackRequest( self.requestName, self.requestString )
      if not update["OK"]:
        self.error( "handleRequest: error when putting back request: %s" % update["Message"] )
    ## return at least
    return ret
Beispiel #12
0
  def _connect(self):
    """ Establish the connection.
        It uses the URL discovered in __discoverURL.
        In case the connection cannot be established, __discoverURL
        is called again, and _connect calls itself.
        We stop after trying self.__nbOfRetry * self.__nbOfUrls

    """
    # Check if the useServerCertificate configuration changed
    # Note: I am not really sure that  all this block makes
    # any sense at all since all these variables are
    # evaluated in __discoverCredentialsToUse
    if gConfig.useServerCertificate() != self.__useCertificates:
      if self.__forceUseCertificates is None:
        self.__useCertificates = gConfig.useServerCertificate()
        self.kwargs[self.KW_USE_CERTIFICATES] = self.__useCertificates
        # The server certificate use context changed, rechecking the transport sanity
        result = self.__checkTransportSanity()
        if not result['OK']:
          return result

    # Take all the extra credentials
    self.__discoverExtraCredentials()
    if not self.__initStatus['OK']:
      return self.__initStatus
    if self.__enableThreadCheck:
      self.__checkThreadID()

    gLogger.debug("Connecting to: %s" % self.serviceURL)
    try:
      # Calls the transport method of the apropriate protocol.
      # self.__URLTuple[1:3] = [server name, port, System/Component]
      transport = gProtocolDict[self.__URLTuple[0]]['transport'](self.__URLTuple[1:3], **self.kwargs)
      # the socket timeout is the default value which is 1.
      # later we increase to 5
      retVal = transport.initAsClient()
      # If we have an issue connecting
      if not retVal['OK']:
        # We try at most __nbOfRetry each URLs
        if self.__retry < self.__nbOfRetry * self.__nbOfUrls - 1:
          # Recompose the URL (why not using self.serviceURL ? )
          url = "%s://%s:%d/%s" % (self.__URLTuple[0], self.__URLTuple[1], int(self.__URLTuple[2]), self.__URLTuple[3])
          # Add the url to the list of banned URLs if it is not already there. (Can it happen ? I don't think so)
          if url not in self.__bannedUrls:
            self.__bannedUrls += [url]
            # Why only printing in this case ?
            if len(self.__bannedUrls) < self.__nbOfUrls:
              gLogger.notice("Non-responding URL temporarily banned", "%s" % url)
          # Increment the retry couunter
          self.__retry += 1
          # If it is our last attempt for each URL, we increase the timeout
          if self.__retryCounter == self.__nbOfRetry - 1:
            transport.setSocketTimeout(5)  # we increase the socket timeout in case the network is not good
          gLogger.info("Retry connection", ": %d to %s" % (self.__retry, self.serviceURL))
          # If we tried all the URL, we increase the global counter (__retryCounter), and sleep
          if len(self.__bannedUrls) == self.__nbOfUrls:
            self.__retryCounter += 1
            # we run only one service! In that case we increase the retry delay.
            self.__retryDelay = 3. / self.__nbOfUrls if self.__nbOfUrls > 1 else 2
            gLogger.info("Waiting %f seconds before retry all service(s)" % self.__retryDelay)
            time.sleep(self.__retryDelay)
          # rediscover the URL
          self.__discoverURL()
          # try to reconnect
          return self._connect()
        else:
          return retVal
    except Exception as e:
      gLogger.exception(lException=True, lExcInfo=True)
      return S_ERROR("Can't connect to %s: %s" % (self.serviceURL, repr(e)))
    # We add the connection to the transport pool
    trid = getGlobalTransportPool().add(transport)

    return S_OK((trid, transport))