
    |                     l   d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlZddlZddl	m
Z
 ddl	mZ ddlmZ dd	lmZ dd
lmZ ddlZddlmZ ddlmZ dZ	 ddlZe
 eedd      ZdZej4                  ej6                  ej8                  efZdZd Z G d de       Z! e!       Z"ddZ#d Z$y# e$ r Y Xw xY w)z+Caching logic for checking if we're on GCE.    )absolute_import)division)unicode_literalsN)config)
properties)gce_read)files)retry)http_client)urllib_errorCertificateErroriX  zName or service not knownc                     ~ ~~t        |t              syt        |t        j                        rt        t        j                  |      v ryy)z;Decides if we need to retry the metadata server connection.FT)
isinstance(_POSSIBLE_ERRORS_GCE_METADATA_CONNECTIONr   URLError_DOMAIN_NAME_RESOLVE_ERROR_MSGsix	text_type)exc_type	exc_valueexc_tracebackstates       0lib/googlecloudsdk/core/credentials/gce_cache.py$_ShouldRetryMetadataServerConnectionr   8   s@     u	IG	HL112$i(@@	    c                   x    e Zd ZdZddZddZd Zd Zd Zd Z	d	 Z
d
 Z ej                  de      d        Zy)_OnGCECachea  Logic to check if we're on GCE and cache the result to file or memory.

  Checking if we are on GCE is done by issuing an HTTP request to a GCE server.
  Since HTTP requests are slow, we cache this information. Because every run
  of gcloud is a separate command, the cache is stored in a file in the user's
  gcloud config dir. Because within a gcloud run we might check if we're on GCE
  multiple times, we also cache this information in memory.
  A user can move the gcloud instance to and from a GCE VM, and the GCE server
  can sometimes not respond. Therefore the cache has an age and gets refreshed
  if more than _GCE_CACHE_MAX_AGE passed since it was updated.
  Nc                 R    || _         || _        t        j                         | _        y N)	connectedexpiration_time	threadingLock	file_lock)selfr    r!   s      r   __init__z_OnGCECache.__init__R   s    DN*D^^%DNr   c                     | j                  |      }||S  | j                  | j                           | j                  |      }||S | j                         S )af  Check if we are on a GCE machine.

    Checks, in order:
    * in-memory cache
    * on-disk cache
    * metadata server

    If we read from one of these sources, update all of the caches above it in
    the list.

    If check_age is True, then update all caches if the information we have is
    older than _GCE_CACHE_MAX_AGE. In most cases, age should be respected. It
    was added for reporting metrics.

    Args:
      check_age: bool, determines if the cache should be refreshed if more than
        _GCE_CACHE_MAX_AGE time passed since last update.

    Returns:
      bool, if we are on GCE or not.
    	check_age)_CheckMemory_WriteMemory
_CheckDiskCheckServerRefreshAllCaches)r%   r)   on_gces      r   GetOnGCEz_OnGCECache.GetOnGCEW   sf    , 3FmDt()3Fm++--r   c                     | j                         }| j                  |       | j                  |t        j                         t        z          |S r   )_CheckServerWithRetry
_WriteDiskr+   time_GCE_CACHE_MAX_AGE)r%   r.   s     r   r-   z'_OnGCECache.CheckServerRefreshAllCachesx   s=    '')FOOFfdiik,>>?Mr   c                     |s| j                   S | j                  r-| j                  t        j                         k\  r| j                   S y r   )r    r!   r3   )r%   r)   s     r   r*   z_OnGCECache._CheckMemory~   s8    ^^ 4 4		 C^^r   c                      || _         || _        y r   )r    r!   )r%   r.   r!   s      r   r+   z_OnGCECache._WriteMemory   s    DN*Dr   c                    t        j                         j                         }| j                  5  	 t	        j
                  |      j                  }|t        z   }t        j                  |      }|t        j                  d      k(  |fcddd       S # t        t        t        j                  f$ r Y ddd       yw xY w# 1 sw Y   yxY w)zReads cache from disk.TNNN)r   PathsGCECachePathr$   osstatst_mtimer4   r	   ReadFileContentsr   r   OSErrorIOErrorError)r%   gce_cache_pathmtimer!   gcecache_file_values        r   r,   z_OnGCECache._CheckDisk   s    \\^002N	'00"44#44^D"cmmD&99?J 
 w,   
 
s)   B=ABB:/B=9B::B==Cc                 *   t        j                         j                         }| j                  5  	 t	        j
                  |t        j                  |      d       ddd       y# t        t        t        j                  f$ r Y )w xY w# 1 sw Y   yxY w)zUpdates cache on disk.T)privateN)r   r9   r:   r$   r	   WriteFileContentsr   r   r?   r@   rA   )r%   r.   rB   s      r   r2   z_OnGCECache._WriteDisk   sq    \\^002N		CMM&14	A 
 w,  		 
s(   B	+A%%BB	BB		Bc                 B    	 | j                         S # t        $ r Y yw xY w)NF)_CheckServerr   r%   s    r   r1   z!_OnGCECache._CheckServerWithRetry   s(      3 s    	   )max_retrialsshould_retry_ifc                     t        j                  t         j                  t        j                  j
                  j                  j                               j                         S r   )	r   ReadNoProxy'GOOGLE_GCE_METADATA_NUMERIC_PROJECT_URIr   VALUEScomputegce_metadata_check_timeout_secGetIntisdigitrJ   s    r   rI   z_OnGCECache._CheckServer   sG     88!!@@GGI gir   r8   T)__name__
__module____qualname____doc__r&   r/   r-   r*   r+   r,   r2   r1   r
   RetryOnExceptionr   rI    r   r   r   r   E   sY    
&
.B+" 5&JLLr   r   c                 ,    t         j                  |       S )zAHelper function to abstract the caching logic of if we're on GCE.)_SINGLETON_ON_GCE_CACHEr/   r(   s    r   r/   r/      s    	 	)	))	44r   c                  *    t         j                         S )z@Force rechecking server status and refreshing of all the caches.)r^   r-   r\   r   r   ForceCacheRefreshr`      s    	 	<	<	>>r   rV   )%rZ   
__future__r   r   r   r;   socketr"   r3   googlecloudsdk.corer   r   googlecloudsdk.core.credentialsr   googlecloudsdk.core.utilr	   r
   r   	six.movesr   r   SslCertificateErrorsslImportErrorgetattrr4   r   errorHTTPExceptionr   r   r   objectr   r^   r/   r`   r\   r   r   <module>rn      s    2 &  ' 	    & * 4 * * 
 ! "  ?%7> 
 -9,A,A6<<,7,E,E,?,A ( "= 
p& ph &- 5
?u  s   B+ +B32B3