
    %                       S r SSKJr  SSKrSSKJr  SSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKrSSKrSSKJrJr  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SrSr Sr!\RD                  " S5      r#\RH                  SS j5       r% " S S\RL                  5      r'\RP                   " S S5      5       r)\RP                   " S S5      5       r* " S S\RV                  5      r,g)zClasses and utils for Storage diagnostics.

Storage diagnostics are a bunch of tests that can be run to diagnose issues
with the storage system.
    )annotationsN)MutableMapping)DictList)errors)utils)execution_utils)log)
console_io)progress_tracker)filesCLOUDSDK_STORAGE_THREAD_COUNTCLOUDSDK_STORAGE_PROCESS_COUNTzN/Az%.*following URLs matched no objects.*c              #  t   #    [         R                   " 5       nSv   [         R                   " 5       nX2-
  X'   g7f)a#  A context manager that records the time it takes to run a block of code.

Args:
  key: The key to use in the result dictionary.
  result: The dictionary to store the result in. The time taken to run the
    block of code will be stored in this dictionary with the given key.

Yields:
  None
N)time)keyresultt0t1s       =lib/googlecloudsdk/command_lib/storage/diagnose/diagnostic.pytime_recorderr   5   s)      yy{"yy{"&+s   68c                      \ rS rSrSrSrg)DiagnosticIgnorableErrorG   z;Ignorable Exception thrown during the diagnostic execution. N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       r   r   r   G   s    Cr"   r   c                  F    \ rS rSr% SrS\S'   S\S'   SrS\S	'   SS
 jrSrg)DiagnosticOperationResultK   zResult of a operation performed as part of a diagnostic.

Attributes:
  name: The name of the operation.
  result: The result of the operation.
  payload_description: The description of the payload used for running this
    operation.
strnamezDict[any, any]r   Nz
str | Nonepayload_descriptionc                   [         R                  " 5       nUR                  S5        UR                  SR                  U R                  5      5        U R
                  (       a*  UR                  SR                  U R
                  5      5        UR                  SR                  U R                  5      5        UR                  5       $ )NzDiagnostic Operation Result
	Name: {}
zPayload Description: {}
zResult: {}
)ioStringIOwriteformatr'   r(   r   getvalue)selfouts     r   __str__!DiagnosticOperationResult.__str__Z   s    
++-CII-.IIl!!$)),-	ii+2243K3KLMIIn##DKK01<<>r"   r   returnr&   )	r   r   r   r   r    __annotations__r(   r2   r!   r   r"   r   r$   r$   K   s$     	)
$(z(r"   r$   c                  F    \ rS rSr% SrS\S'   S\S'   SrS\S	'   SS
 jrSrg)DiagnosticResultd   zResult of a diagnostic execution.

Attributes:
  name: The name of the diagnostic.
  operation_results: The results of the operations performed as part of this
    diagnostic.
  metadata: Additional metadata associated with the diagnostic.
r&   r'   zList[DiagnosticOperationResult]operation_resultsNzDict[any, any] | Nonemetadatac                   [         R                  " 5       nUR                  S5        UR                  SR                  U R                  5      5        U R
                  (       a*  UR                  SR                  U R
                  5      5        UR                  S5        U R                   H   nUR                  [        U5      S-   5        M"     UR                  5       $ )NzDiagnostic Result
r*   zMetadata: {}
z
Operation Results:

)	r+   r,   r-   r.   r'   r;   r:   r&   r/   )r0   r1   operation_results      r   r2   DiagnosticResult.__str__s   s    
++-CII#$IIl!!$)),-}}	ii ''67II&' 22	ii$%,- 3<<>r"   r   r4   )	r   r   r   r   r    r6   r;   r2   r!   r   r"   r   r8   r8   d   s$     	)44$((!(	r"   r8   c                      \ rS rSrSrSr\\R                  SS j5       5       r	S r
\R                  S 5       rS rS r S       SS	 jjrSS
 jrSSS jjrSS jrS rSS jrSrg)
Diagnostic   zBase class for storage diagnostics.

This class provides a framework for writing diagnostics. Subclasses can
override the pre-processing, diagnostic and post-processing steps as needed.
The execute method is the entry point for running the diagnostic.
Nc                    g)zThe name of the diagnostic.Nr   r0   s    r   r'   Diagnostic.name   s     	r"   c                J    [         R                  R                  5       U l        g)zPre-processing step for the diagnostic.

This method is called before the diagnostic is run. Implementing child
classes can override this method to perform actions necessary for
running diagnostics like file creation, setting configurations etc.
N)osenvironcopy_old_env_varsrD   s    r   _pre_processDiagnostic._pre_process   s     *Dr"   c                    g)z|Runs the diagnostic.

This method is called after the pre-processing step and is expected to
perform the actual diagnostic.
Nr   rD   s    r   _runDiagnostic._run   s     	r"   c                J    U R                   b  U R                   [        l        gg)zPost-processing step for the diagnostic.

This method is called after the diagnostic is run. Implemeneting child
classes can override this method to perform clean up actions, aggregating
metrics, etc.
N)rJ   rG   rH   rD   s    r   _post_processDiagnostic._post_process   s"     %%%bj &r"   c                   [         R                  R                  SU R                   S35        [        R
                  " 5           U R                  5         U R                  5         U R                  5         [         R                  R                  SU R                   35        SSS5        g! [         a/  n[         R                  " U R                   SU 35         SnANySnAff = f! U R                  5         f = f! , (       d  f       g= f)zExecutes the diagnostic.zRunning diagnostic: z...z Diagnostic execution failed: NzFinished running diagnostic: )r
   statusPrintr'   r	   RaisesKeyboardInterruptrK   rN   r   errorrQ   )r0   es     r   executeDiagnostic.execute   s    JJ+DII;c:;		0	0	2		
 		jj6tyykBC 
3	2
 & C		TYYK=aSABBC 	 
3	2sB   C; B*%<C;*
C#4%CC&C##C&&C88C;;
D	c           
         [        U5      n [        R                  " 5       U l        [        R
                  " SU SU R                  R                   3SS9   [        U5       H  n[        R                  " U R                  R                  USSSS9 nX   nUS	:  a7  [        Xs5      nUR                  U R                  U5      5        Xx-  nUS	:  a  M7  S
S
S
5        U R                  R                  WR                  5        M     S
S
S
5        g! , (       d  f       N@= f! , (       d  f       g= f! [         ["        [$        R&                  4 a/  n	[(        R*                  " SR-                  U	5      5         S
n	A	gS
n	A	ff = f)a!  Creates test files in a temporary directory.

Args:
  object_sizes: The size of each object to create.
  file_prefix: The prefix to use for the file names.
  chunk_size: The size of each chunk to write to the file.

Returns:
  True if the files were created successfully, False otherwise.
z	Creating z test files in T)autotickFzw+tzutf-8)dirprefixdeletemodeencodingr   NzFailed to create test files: {})len
file_utilsTemporaryDirectorytemp_dirr   ProgressTrackerpathrangetempfileNamedTemporaryFileminr-   _generate_random_string_filesappendr'   OSErrorEnvironmentErrorr   OperationCancelledErrorr
   warningr.   )
r0   object_sizesfile_prefix
chunk_sizeobject_countifbytes_remainingcurrent_chunk_sizerX   s
             r   _create_test_filesDiagnostic._create_test_files   sM     |$L? 335dm++l^?4==3E3E2F
G |$A**--$$  *oO!A%#&#C ggd223EFG3o "A% ++

QVV
$ %	$   $ %z'I'IJ ?	kk3::1=>>?sO   A	D/ ;DA D1DD/ 
DD
D,(D/ ,D/ /E=%E88E=c                <    [        U5      [        R                  U'   g)zSets the environment variable to the given value.

Args:
  variable_name: Name of the environment variable.
  variable_value: Value of the environment variable.
N)r&   rG   rH   )r0   variable_namevariable_values      r   _set_env_variableDiagnostic._set_env_variable   s     !$N 3BJJ}r"   c                    SSUUS/n[         R                  " XCS9u  pVU(       a  [        SR                  XU5      5      eg)zRuns the gcloud cp command.

Args:
  source_url: Source url for the cp command.
  destination_url: Destination url for the cp command.
  in_str: The input to pass to the gcloud cp command.

Raises:
  DiagnosticIgnorableError: If the cp command fails.
storagecpz--verbosity=debug)in_strz0Failed to copy objects from source {} to {} : {}N)r   
run_gcloudr   r.   )r0   
source_urldestination_urlr   args_errs          r   _run_cpDiagnostic._run_cp   sV     	D d2FA
$
<
C
C3  r"   c                   SSU U S3/n[         R                  " U5      u  pEU(       aX  [        R                  U5      (       a  [        R
                  " SU SU S35        g	[        R                  " SU SU SU 35        g	g	)
z<Cleans up objects in the given bucket with the given prefix.r   rm*zNo objects to delete in z with prefix .zFailed to clean up objects in z : N)r   r   _NO_OBJECT_TO_DELETE_REGEXPsearchr
   inforr   )r0   
bucket_urlobject_prefixr   r   r   s         r   _clean_up_objectsDiagnostic._clean_up_objects  s     	,}oQ'D
 d#FA
	$	+	+C	0	0&zl-aP	
 	,ZL 9c#(	
 r"   c                    U R                   b   U R                  [        U R                   5        U R                  b!  U R                  [        U R                  5        gg)z8Sets the process and thread count environment variables.N)_process_countr   _PROCESS_COUNT_ENV_VAR_thread_count_THREAD_COUNT_ENV_VARrD   s    r   _set_parallelism_env_vars$Diagnostic._set_parallelism_env_vars  sM    &
3T5H5HI%
2D4F4FG &r"   c                D    SR                  S [        U5       5       5      $ )zGenerates a random string of the given length.

Args:
  length: The length of the string to generate.

Returns:
  A random string of the given length.
 c              3     #    U  HK  n[         R                  " [        R                  [        R                  -   [        R
                  -   5      v   MM     g 7fN)randomchoicestringascii_lettersdigitspunctuation).0r   s     r   	<genexpr>5Diagnostic._generate_random_string.<locals>.<genexpr>*  s=      A 	f**V]]:V=O=OOPPs   AA)joinrh   )r0   lengths     r   rl   "Diagnostic._generate_random_string!  s&     77 v  r"   )rJ   re   r4   )i   )rs   z	List[int]rt   r   ru   intr5   bool)r~   r&   r   anyr   )r   r&   r   r&   )r   r&   r   r&   r5   None)r   r   r5   r&   )r   r   r   r   r    rJ   propertyabcabstractmethodr'   rK   rN   rQ   rY   r{   r   r   r   r   rl   r!   r   r"   r   rA   rA      s     -	  	+ 	 	&D$ $	)) ) 	)
 )V44
&Hr"   rA   )r   r&   r   zMutableMapping[str, float]r5   r   )-r    
__future__r   r   collections.abcr   
contextlibdataclassesr+   rG   r   rer   ri   r   typingr   r   "googlecloudsdk.command_lib.storager   +googlecloudsdk.command_lib.storage.diagnoser   googlecloudsdk.corer	   r
   googlecloudsdk.core.consoler   r   googlecloudsdk.core.utilr   rc   r   r   PLACEHOLDER_METRIC_VALUEcompiler   contextmanagerr   Errorr   	dataclassr$   r8   ABCrA   r   r"   r   <module>r      s    # 
 *   	 	  	     5 = / # 2 8 87 9    jj, 
  "Dv|| D   0   4n nr"   