
    %                       d Z ddlmZ ddl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
Z
ddlZddlZddlZddlZddlmZ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mZ ddlmZ ddlmZ dZdZ dZ! ejD                  d      Z#ejH                  dd       Z% G d dejL                        Z'ejP                   G d d             Z)ejP                   G d d             Z* G d dejV                        Z,y)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   K   t        j                          }d t        j                          }||z
  || <   yw)a1  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{"R&+s   68c                      e Zd ZdZy)DiagnosticIgnorableErrorz;Ignorable Exception thrown during the diagnostic execution.N)__name__
__module____qualname____doc__     r   r   r   G   s    Cr   r   c                  <    e Zd ZU dZded<   ded<   dZded<   d
d	Zy)DiagnosticOperationResultzResult 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                   t        j                         }|j                  d       |j                  dj                  | j                               | j
                  r*|j                  dj                  | j
                               |j                  dj                  | j                               |j                         S )NzDiagnostic Operation Result
	Name: {}
zPayload Description: {}
zResult: {}
)ioStringIOwriteformatr#   r$   r   getvalue)selfouts     r   __str__z!DiagnosticOperationResult.__str__Z   s    
++-CII-.IIl!!$)),-	ii+2243K3KLMIIn##DKK01<<>r   returnr"   )r   r   r   r   __annotations__r$   r.   r   r   r   r!   r!   K   s$     	)
$(z(r   r!   c                  <    e Zd ZU dZded<   ded<   dZded<   d
d	Zy)DiagnosticResultzResult 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                   t        j                         }|j                  d       |j                  dj                  | j                               | j
                  r*|j                  dj                  | j
                               |j                  d       | j                  D ]  }|j                  t        |      dz          ! |j                         S )NzDiagnostic Result
r&   zMetadata: {}
z
Operation Results:

)	r'   r(   r)   r*   r#   r5   r4   r"   r+   )r,   r-   operation_results      r   r.   zDiagnosticResult.__str__s   s    
++-CII#$IIl!!$)),-}}	ii ''67II&' 22	ii$%,- 3<<>r   r/   )r   r   r   r   r1   r5   r.   r   r   r   r3   r3   d   s$     	)44$((!(	r   r3   c                      e Zd ZdZdZeej                  dd              Zd Z	ej                  d        Z
d Zd Z	 d	 	 	 	 	 	 	 ddZdd	Zddd
ZddZd ZddZy)
Diagnostica  Base 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                     y)zThe name of the diagnostic.Nr   r,   s    r   r#   zDiagnostic.name   s     	r   c                J    t         j                  j                         | _        y)a  Pre-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_varsr<   s    r   _pre_processzDiagnostic._pre_process   s     *Dr   c                     y)zRuns the diagnostic.

    This method is called after the pre-processing step and is expected to
    perform the actual diagnostic.
    Nr   r<   s    r   _runzDiagnostic._run   s     	r   c                H    | j                   | j                   t        _        yy)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)rA   r>   r?   r<   s    r   _post_processzDiagnostic._post_process   s"     %%%bj &r   c                   t         j                  j                  d| j                   d       t	        j
                         5  	 | j                          | j                          | j                          t         j                  j                  d| j                          ddd       y# t        $ r.}t        j                  | j                   d|        Y d}~wd}~ww xY w# | j                          w xY w# 1 sw Y   yxY w)zExecutes the diagnostic.zRunning diagnostic: z...z Diagnostic execution failed: NzFinished running diagnostic: )r
   statusPrintr#   r	   RaisesKeyboardInterruptrB   rD   r   errorrF   )r,   es     r   executezDiagnostic.execute   s    JJ+DII;c:;		0	0	2		
 		jj6tyykBC 
3	2
 & C		TYYK=aSABBC 	 
3	2sB   C8 B)$<C8)	C 2$CC#C  C##C55C88Dc           	        t        |      }	 t        j                         | _        t	        j
                  d| d| j                  j                   d      5  t        |      D ]  }t        j                  | j                  j                  |ddd      5 }||   }|d	kD  r7t        ||      }|j                  | j                  |             ||z  }|d	kD  r7d
d
d
       | j                  j                  j                          	 d
d
d
       y# 1 sw Y   :xY w# 1 sw Y   yxY w# t         t"        t$        j&                  f$ r.}	t)        j*                  dj-                  |	             Y d
}	~	yd
}	~	ww xY w)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*   )
r,   object_sizesfile_prefix
chunk_sizeobject_countifbytes_remainingcurrent_chunk_sizerL   s
             r   _create_test_fileszDiagnostic._create_test_files   sO     |$L? 335dm++l^?4==3E3E2F
G |$A**--$$  *1oO!A%#&
#C ggd223EFG!33o "A% ++

QVV
$ %	$  $ %z'I'IJ ?	kk3::1=>>?sO   A
D' =DAD/DD' DDD$ D' $D' 'E3$E..E3c                <    t        |      t        j                  |<   y)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"   r>   r?   )r,   variable_namevariable_values      r   _set_env_variablezDiagnostic._set_env_variable   s     !$N 3BJJ}r   c                    dd||dg}t        j                  ||      \  }}|rt        dj                  |||            y)a  Runs 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*   )r,   
source_urldestination_urlrv   args_errs          r   _run_cpzDiagnostic._run_cp   s\     	D d62FAs
$
<
C
C/3  r   c                    dd| | dg}t        j                  |      \  }}|rQt        j                  |      rt	        j
                  d| d| d       y	t	        j                  d| d| d|        y	y	)
z<Cleans up objects in the given bucket with the given prefix.rt   rm*zNo objects to delete in z with prefix .zFailed to clean up objects in z : N)r   rw   _NO_OBJECT_TO_DELETE_REGEXPsearchr
   infore   )r,   
bucket_urlobject_prefixrz   r{   r|   s         r   _clean_up_objectszDiagnostic._clean_up_objects  s     	,}oQ'D
 d#FAs
	$	+	+C	0&zl-aP	
 	,ZL 9c#(	
 r   c                    | j                    | j                  t        | j                          | j                  !| j                  t        | j                         yy)z8Sets the process and thread count environment variables.N)_process_countrr   _PROCESS_COUNT_ENV_VAR_thread_count_THREAD_COUNT_ENV_VARr<   s    r   _set_parallelism_env_varsz$Diagnostic._set_parallelism_env_vars  sM    &
3T5H5HI%
2D4F4FG &r   c                D    dj                  d t        |      D              S )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     K   | ]I  }t        j                  t        j                  t        j                  z   t        j
                  z          K y wN)randomchoicestringascii_lettersdigitspunctuation).0r{   s     r   	<genexpr>z5Diagnostic._generate_random_string.<locals>.<genexpr>*  s;      A 	f**V]]:V=O=OOPs   AA)joinr[   )r,   lengths     r   r_   z"Diagnostic._generate_random_string!  s&     77 v  r   r/   )i   )rf   z	List[int]rg   r   rh   intr0   bool)rp   r"   rq   anyr   )rx   r"   ry   r"   )r   r"   r   r"   r0   None)r   r   r0   r"   )r   r   r   r   rA   propertyabcabstractmethodr#   rB   rD   rF   rM   rn   rr   r}   r   r   r_   r   r   r   r:   r:      s     -	  	+ 	 	&D$ $	)) ) 	)
 )V44
&Hr   r:   )r   r"   r   zMutableMapping[str, float]r0   r   )-r   
__future__r   r   collections.abcr   
contextlibdataclassesr'   r>   r   rer   r\   r   typingr   r   "googlecloudsdk.command_lib.storager   +googlecloudsdk.command_lib.storage.diagnoser   googlecloudsdk.corer	   r
   googlecloudsdk.core.consoler   r   googlecloudsdk.core.utilr   rV   r   r   PLACEHOLDER_METRIC_VALUEcompiler   contextmanagerr   Errorr   	dataclassr!   r3   ABCr:   r   r   r   <module>r      s    # 
 *   	 	  	     5 = / # 2 8 87 9   (bjj, 
  "Dv|| D   0   4n nr   