
    %                        S r SSKJr  SSKJ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
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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!r!Sr"Sr# S/S jr$S r% " S S5      r& S0S jr'S r(S r)S r*S r+S r,S r-S r.S  r/S! r0S" r1S# r2S$ r3S% r4S& r5S' r6S( r7S) r8S* r9S+ r:S, r;S- r<S. r=g)1z,SSH/SCP utilities for Cloud TPU VM commands.    )absolute_import)division)unicode_literalsN)encoding_helper)HttpConflictError)	HttpError)base_classes)
exceptions)
iap_tunnel)	ssh_utils)util)ssh)execution_utils)log)
FileWriterzssh-keysa  
Please check the following:
- Verify that the 'compute.disableGuestAttributesAccess'
  Organization Policy Constraint is not enforced in your project.
- Verify that this TPU was created after March 24, 2022.
- Check that you have allowed IAP to connect to instances in your
  firewall (https://cloud.google.com/iap/docs/using-tcp-forwarding#create-firewall-rule),
  and that the TPU is in READY state with HEALTHY health.
c                     U R                  SSSS9  U(       a  U R                  SUSS9  U(       a3  U R                  5       nUR                  SSS	S
9  UR                  SSSS
9  gU R                  SSS	S
9  g)zEArguments that are common and specific to both TPU VM/QR SSH and SCP.--worker0aS            TPU worker to connect to. The supported value is a single 0-based
          index of the worker in the case of a TPU Pod. When also using the
          `--command` flag, it additionally supports a comma-separated list
          (e.g. '1,4,6'), range (e.g. '1-3'), or special keyword ``all" to
          run the command concurrently on each of the specified workers.

          Note that when targeting multiple workers, you should run 'ssh-add'
          with your private key prior to executing the gcloud command. Default:
          'ssh-add ~/.ssh/google_compute_engine'.
          )defaulthelp--batch-sizea'              Batch size for simultaneous command execution on the client's side.
            When using a comma-separated list (e.g. '1,4,6') or a range (e.g. '1-3') or
            ``all`` keyword in `--worker` flag, it executes the command
            concurrently in groups of the batch size. This flag takes a
            value greater than 0 to specify the batch size to control the
            concurrent connections that can be established with the TPU
            workers, or the special keyword ``all`` to allow the concurrent
            command executions on all the specified workers in `--worker` flag.
            Maximum value of this flag should not be more than the number of
            specified workers, otherwise the value will be treated as
            ``--batch-size=all``.
            z--internal-ip
store_truea              Connect to TPU VMs using their internal IP addresses rather than their
            external IP addresses. Use this to connect from a Google Compute
            Engine VM to a TPU VM on the same VPC network, or between two peered
            VPC networks.
            )actionr   z--tunnel-through-iapa          Tunnel the SSH connection through Cloud Identity-Aware Proxy for TCP
        forwarding.

        This flag must be specified to attempt to connect via IAP tunneling. If it
        is not set, and connection to a Cloud TPU VM without external IP address
        is attempted from outside the network, then the command will fail.

        To use IAP tunneling, there must be firewall access to the SSH port for
        the IAP TCP IP address range for the network the TPU is created in. See
        the [user guide](https://cloud.google.com/iap/docs/using-tcp-forwarding)
        for more details.

        To learn more, see the
        [IAP for TCP forwarding documentation](https://cloud.google.com/iap/docs/tcp-forwarding-overview).
        N)add_argumentadd_mutually_exclusive_group)parser
enable_iapenable_batchingenable_batching_defaultrouting_groups        9lib/googlecloudsdk/command_lib/compute/tpus/tpu_vm/ssh.pyAddTPUSSHArgsr"   7   s     	
   
'  " 779M  	   *   	    c                 B   XR                   L a  gXR                  L a&  [        R                  " SR	                  X 5      5        gU UR
                  UR                  UR                  UR                  UR                  4;   a&  [        R                  " SR	                  X 5      5        gU UR                  UR                  UR                  UR                  4;   a  [        R                  " U 5      eXR                   UR"                  4;   a  [        R$                  " U 5      eg)zValidates the TPU's state.

Prints warnings or throws exceptions when appropriate.

Args:
  state: the state of the TPU.
  state_enum: the enum for all TPU states.
  tpu_name: the name of the TPU VM.
zVThe TPU VM "{}" is in state "{}", therefore the TPU may not be available or reachable.zThe TPU VM "{}" is in state "{}", therefore the TPU may not be available or reachable. If the connection fails, please try again later.N)READYSTATE_UNSPECIFIEDr   warningformatCREATINGSTARTING	REPAIRINGHIDINGUNHIDINGSTOPPEDSTOPPINGDELETINGHIDDENtpu_exceptionsTPUInUnusableState	PREEMPTED
TERMINATEDTPUInUnusableTerminalState)state
state_enumtpu_names      r!   ValidateTPUStater:      s    ,,,KK	##)6(#:   KK	&)
 	  
+
+E
22%%z'<'<==

3
3E
:: >r#   c                       \ rS rSrSrS rSrg)IPAddresses   z/Worker is a holder for the worker IP addresses.c                     Xl         X l        g N)
ip_addressinternal_address)selfr@   rA   s      r!   __init__IPAddresses.__init__   s     O,r#   )rA   r@   N)__name__
__module____qualname____firstlineno____doc__rC   __static_attributes__ r#   r!   r<   r<      s
    7-r#   r<   c                 :   [        SU5      n[        U5       VVs/ s H  u  pVXT-  S:X  d  M  UPM     nnn[        U5      n[        R                  " U 5      R                  5       S:X  a  [        [        U5      5      n	GO[        5       n	U R                  S5      n
U
 H  nU(       d  M  SU;   a  UR                  S5      n[        U5      S:w  d  US   (       a
  US   (       d&  [        R                  " SSR                  U5      5      e[        US   5      [        US   5      pX:  a&  [        R                  " SSR                  U5      5      eU	R                  [        XS-   5      5        M   U	R                  [        U5      5        M     U	(       d  [        R                  " SS
5      e[        U	5      nX:  a)  [        R                  " SSR                  XS-
  5      5      e0 nU	 Hv  nUU   R"                  nU(       dL  UU   R$                  (       a8  UU   R$                  R&                  (       a  UU   R$                  R&                  nOUn[)        UU5      UU'   Mx     U$ s  snnf ! [          a'    [        R                  " SS	R                  U5      5      ef = f)zGParses the --worker flag into a dict of worker indexes to IP addresses.   r   ALL,-   r   zfound malformed range "{}".z6unable to parse worker ID {}. Please only use numbers.zAno worker specified, or none were parsed from the argument value.zworker index {} is larger than the valid worker indexes on this TPU VM. Please only use indexes in the range [0, {}], inclusive.)max	enumeratelensix	text_typeupperlistrangesetsplitr
   InvalidArgumentExceptionr(   intupdateadd
ValueError	ipAddressaccessConfig
externalIpr<   )worker_flagnetwork_endpointsuse_internal_ipsnum_netsmax_num_netsiendpointprimary_network_endpointsn_vmsindexesrangesrboundsstartendmx
worker_ipsworkerrA   r@   s                       r!   ParseWorkerFlagrv      sp   
 Q!, ##455+!	
	Q	 5   '
(%]];%%'505< GeGs#F	v;!6!9F1I337>>qA  ^S^s<337>>qA  	uU!G,-	
++c!f
# 4 


-
-K 
 7|"[

-
-	VB	*	  *f08BB%f-::%f-::EE,V4AALLj#j$Z1ABJv  
E<  	33FMM 	s   I#I#.I))1Jc           	         [         R                  " U 5      R                  5       S:X  a  US:  a  [        R                  " S5        U$  [        U 5      S:  a  [        [        U 5      U5      $ [        5       e! [         aE  n[         R                  " [        R                  " SSR                  U 5      5      U5         SnAgSnAff = f)a  Parses the --batch-size flag and validates the flag value.

Args:
  batch_size_flag: str, batch-size flag argument.
  num_ips: int, number of ip-addresses for the ssh command execution.

Returns:
  int, batch-size value capped at number of workers in num_ips.

Raises:
  InvalidArgumentException, if the batch_size_flag is neither a positive
  integer nor equal to the `all` keyword.
rN   d   zExecuting ssh command on too many workers simultaneously is prone to error. Command may fail. Please consider using `--batch-size` flag if the command fails, for example, --batch-size=100.r   r   zounable to parse the batch size value {}. Please use a positive integer not more than the number of TPU workers.N)rU   rV   rW   r   r'   r]   minr`   
raise_fromr
   r\   r(   )batch_size_flagnum_ipserrors      r!   ParseBatchSizer~     s     	]]?#))+u4}	kk N	_		!3'11l 
	nn

-
-AAG!B 	 	
s   #A6 ,
A6 6
C ;C  Cc                     / nU  HQ  nUR                   R                   H4  nUR                  S:X  d  M  UR                  UR                  SS 5          MO     MS     U$ )zReturns the host key suffixes.ssh-ed25519N)
queryValueitemskeyappendvalue)guest_attributeshost_key_suffixesworker_guest_attributesitems       r!   _ParseHostKeySuffixesr   /  sX    !1'2288	]	"  BC1 9 "2
 
r#   c                     S/U-  nU S   R                   R                   H'  nUR                  S:X  d  M  UR                  SS X2'     U$    U$ )zEReturns a list with only a single worker's host key suffix populated. r   r   r   Nr   r   r   r   )r   worker_countru   suffixesr   s        r!   _ParseSingleHostKeySuffixr   :  sV    TL (q!,,22dxx= BCh	/	 3 
/r#   c                 ~    X   R                   R                   H!  nUR                  U:X  d  M  UR                  s  $    g r?   r   )r   ru   r   r   s       r!   GetFromGuestAttributesr   D  s5    &1177dxx3ZZ 8 
r#   c                     U(       a8  [        U5      S   n[        U R                  [        UR                  5      U5      $ [        U R                  5      $ )z9Retrieves the host key suffixes from the GuestAttributes.r   )rX   r   guestAttributesrT   networkEndpointsr   )guest_attributes_responsesingle_pod_workerrt   node	worker_ids        r!   %GetHostKeySuffixesFromGuestAttributesr   K  sQ     Z #I$!11D!!"  !!:!J!JKKr#   c                     U(       a7  [        U5      S   n U R                  X4[        R                  " U5      5      nU$  U R                  X45      nU$ ! [         a     gf = f! [         a     gf = f)zRetrieves the GuestAttributes.r   N)rX   GetGuestAttributesrU   rV   r   )
tpu_helperr   rt   r9   zoner   r   s          r!   r   r   Z  s     Z #I","?"?
#--4# 
#"	","?"?"O 
#"    s#   &A  A# 
A A #
A0/A0c                     [         R                  " U 5      nSU;   a"  SUS   ;   a  US   S   R                  5       S:H  $ g)z-Returns true if the node has OSLogin enabled.metadatazenable-osloginTRUEN)r   MessageToDictrW   )r   	node_dicts     r!   TpuHasOsLoginEnabledr   p  sI    ++D1)9!1Yz5J!JZ !1288:fDD	r#   c                     U (       a  U R                   (       d  gU R                    Vs/ s H$  o"R                  [        :X  d  M  UR                  PM&     nnU(       d  gXS   ;   $ s  snf )zReturns true if the metadata has the SSH key.

Args:
  metadata: Project metadata.
  public_key: The SSH key.

Returns:
  True if present, False if not present.
Fr   )r   r   SSH_KEYS_METADATA_KEYr   )r   
public_keyr   matching_valuess       r!   _MetadataHasSSHKeyr   x  s[     x~~%^^+Txx;P/Pjdjj^   
	q)	))s   A$A$c                    [        U R                  U5      (       a   [        R                  R	                  S5        g[
        R                  " U5      nSnSU;   a  [        US   ;   a  US   [           nXW;   a  [        R                  " S5        gUSU-   -  nUR                  R                  UR                  UR                  [        US9S9n UR                  UUUSS	5        g! [         a     gf = f)
zCVerifies that instance has SSH key, and adds it in case it doesn't.z9SSH key found in project metadata; not updating instance.Nr   r   z:SSH key found in instance metadata; not updating instance.
)r   r   r   )r   z-Propagating SSH public key to all TPU workers)r   commonInstanceMetadatar   statusPrintr   r   r   debugmessagesNodeUpdateMetadataKeyr   
UpdateNoder   )	projectr   r   r9   r   r   r   ssh_keysnode_for_updates	            r!   AddSSHKeyIfNeededr     s     66
CCJJC ++D1)(9!6)J:O!O$%:;HIIJK

dZ('',,++==&;8 ,  - /

	7 
 		s   C$ $
C10C1c                 x    SR                  X5      nUb%  [        U5      U:  a  USR                  X!   5      -  nU$ )Nz	tpu.{}-{}z-{})r(   rT   )node_idru   r   instance_ids       r!   GetInstanceIDr     sB    ""73+"s+<'='F5<< 1 9::K	r#   c                    SSU /n[         R                  " 5       n[         R                  " 5       n[        R                  " USUR                  UR                  S9nUS:w  aJ  [
        R                  " SR                  UR                  5       5      5        [
        R                  " S5        gUR                  5       n[        UR                  5       5      S	::  a&  [
        R                  " S
R                  U5      5        gUR                  5       S	   nSS/n[         R                  " 5       n[        R                  " USUR                  UR                  S9nUS:w  aJ  [
        R                  " SR                  UR                  5       5      5        [
        R                  " S5        gXgR                  5       ;  a  [        R                  " U 5      eg)z.Verifies that the ssh-agent holds the SSH key.z
ssh-keygenz-lfT)no_exitout_funcerr_funcr   zssh-keygen exited with error {}z:Cannot generate fingerprint of SSH key. Command may stall.NrM   z=ssh-keygen returned fingerprint entry in invalid format: "{}"zssh-addz-lzssh-add exited with error {}z5Cannot retrieve keys in ssh-agent. Command may stall.)ioStringIOr   Execwriter   r   r(   getvaluer'   rT   r[   r2   SSHKeyNotInAgent)identity_filecmd
keygen_outerrretcodefingerprint_entryfingerprintouts           r!   VerifyKeyInAgentr     sl    
um,#{{}*
#  	4*"2"2SYY' \II/66s||~FGKKLM
 ))+		 	 	"#q(IIGNN	

 !'')!,+ 
D#
#  	4#))cii' \II,33CLLNCDKKGH
&

)
)-
88 'r#   c                     U R                  S5      (       d  g[        R                  " 5       nUR                  Ul        UR
                  Ul        X5l        XEl        U$ )zDConstruct an SshTunnelArgs object from command line args and values.tunnel_through_iapN)	IsKnownAndSpecifiedr   SshTunnelArgsprefixtracknamer   r   instance)argsr   r   r   r   ress         r!   CreateSshTunnelArgsr     sL     
	!	!"6	7	7  "#ll#)#+(,	*r#   c                     U  H  nUR                  5         M     U H"  nU(       d  M  [        R                  " U5        M$     g)aT  Waits for all the running ssh threads to complete.

Exits with a nonzero code, if there are any non-zero exit status in ssh
command execution. This ensures that if any command failed on a worker,
we don't end up returning 0 for a value.

Args:
  ssh_threads: List of ssh threads.
  exit_statuses: List of exit status of each ssh execution.
N)joinsysexit)ssh_threadsexit_statuses
ssh_threadr   s       r!   WaitForBatchCompletionr     s5      jOO   fv	hhv r#   c           
         SnSn	[        U5       H  n
 [        R                  R                  SR	                  X5      5        U" XCU5      nU(       aO  U(       a2  [        R                  R                  SR	                  X5      5        XU'   [
        R                  " U5          g	   g	! [        R                   a  nXS-
  :X  a  U(       a  SX!'   UeU(       a  [        R                  R                  S5        [        R                  R                  SR	                  U [        R                  " U5      5      5        [        R                  " U	5         S	nAGME  S	nAff = f)
z1Attempts to connect to a worker using SSH or SCP.
      z){}: Attempting to connect to worker {}...zL##### Command execution on worker {} failed with exit status {}. Continuing.rM      zFailed to execute command on multiple workers. This may have happened if you have not added your SSH key to your ssh-agent using "ssh-add ~/.ssh/google_compute_engine".zRetrying: {} command error: {}N)rY   r   r   r   r(   r   r   r   CommandErrorrU   rV   timesleep)command_nameru   r   r   envoutput_filemultiple_workersrun_cmdmax_attemptssleep_intervalri   exit_statuses                r!   AttemptRunWithRetriesr     s*    ,. a(	jj
5
<
<
 Ck2k	 
**

, #.
, 
U *  	
Q	 #&-
	

-	
 
jj
*
1
1CMM!,
 jj )s   BB&&E:BEEc           
         SnSnU R                   (       de  UR                  R                  R                  nUR                  R	                  [        UR                  X!R                  5      U R                  S5      n[        R                  " UR                  UR                  5      n[        R                  " XUR                  UR                  5      nSnU R                  S5      (       aM  U R                   (       a<  UR"                  U   n	[%        U UR&                  UR(                  U R*                  U	5      n[        R,                  " UUUR.                  UUUR0                  US9$ )aN  Prepares the SSH command used to SSH into the worker.

Args:
  args: The arguments passed in by the user.
  prepped_node: The object that contains all the necessary information to ssh
    into the node.
  worker: the worker to ssh into.
  ips: The ips of the worker

Returns:
  ssh.SSHCommand that can be used to execute SSH command.
Nr   )remoter   remote_commandextra_flagsoptions	remainderiap_tunnel_args)plain
ssh_helperkeyskey_file	GetConfigr   idr   strict_host_key_checkingr   Remoter@   userParseAndSubstituteSSHFlagsrA   r   r   instance_namesr   release_trackr   r   
SSHCommandcommand_listr   )
r   prepped_noderu   ipsr   r   r   r   r   instance_names
             r!   
SSHPrepCmdr  A  s-    -'	 ++0099M%%//loov/M/MN%%G ::cnnl&7&78&..
CNNC$8$8+ /	2338O8O //7M)""		O 
!!..&&%
 r#   c                 $    UR                  U UUS9$ )Returns a function to run.)explicit_output_fileexplicit_error_fileRun)r   r   output_file_writers      r!   	SSHRunCmdr  t  s!    		-, 
 
 r#   c                    [         R                  " XX45      n[         R                  " U5      n	U	R                  XR                  5      n
[         R
                  " U
5      (       d  [        R                  " SS5      e[        U
R                  U	R                  R                  R                  U 5        [        U
S5      (       d  SO[        U
R                  5      n[!        UR"                  U
R$                  UR&                  U5      Ul        [        UR(                  5      S:  a(  UR*                  (       d  [        R,                  " SS5      eU
R.                  U	R                  R                  R0                  R2                  :X  a  [4        R6                  " S5        [        U
R$                  5      S:  =(       a    [        UR(                  5      S:H  n[9        XUR(                  XR                  5      nUc  UR;                  S	5      (       a~  UR<                  (       am  [4        R>                  " S
5        [4        R@                  RC                  S5        [4        R@                  RC                  [D        5        [F        RH                  " 5       e[4        R>                  " S5        SUl%        O[M        UUUR(                  U
5      Ul%        [N        RP                  " 5       Ul)        URR                  RU                  U5        URR                  RV                  RY                  5       R[                  5       n[         R\                  " X8RR                  5      Ul/        UR`                  (       d  [N        Rb                  " U5      u  nn[d        Rf                  " SUR^                  UUUUU[i        U
5      [j        Rl                  " U5      Rn                  R                  S9	nURp                  =Ul8        nSRs                  X5      nUR`                  (       d3  URt                  (       d"  [w        UR^                  XXR                  U5        UR*                  (       a  UR*                  Ry                  S5      OSUl=        / Ul>        UR~                  (       a%  UR|                  R                  UR~                  5        SnUR                  (       a.  [4        R@                  RC                  SRs                  U5      5        0 UlB        UR;                  S	5      (       a  UR<                  (       a  UR(                   H  nU(       a  SOUn[        UR                  US5      nUcW  [4        R@                  RC                  S5        [4        R@                  RC                  [D        5        [F        RH                  " 5       eUUR                  U'   M     U
R                  UlE        XU'   U$ )a  Prepares TPU VM Node for SSH.

Args:
  tpu_name: The unqualified name of the tpu instance to prepare for SSH.
  user: The username to use for SSH.
  args: The command line arguments used for SSH.
  release_track: The release track/version of client protos to use.
  enable_batching: A bool, True if the user opts into batching requests.
  username_requested: A bool, True if the user has passed a specific username
    in the args.
  prepped_nodes: The list to put resulting prepared nodes into.
  idx: The index specifying which slot in the 'prepped_nodes' list to put the
    output node.

Returns:
  The prepared node that is now ready for SSH.

Raises:
  BadArgumentException: If the node retrieved is not a TPU VM. Non TPU VMs are
    not supported.
  InvalidArgumentException: If there is no command specified, but multiple
    workers are targeted.
  IapTunnelingUnavailable: If IAP Tunneling is not available, the node cannot
    be SSHed into.
TPUthis command is only available for Cloud TPU VM nodes. To access this node, please see https://cloud.google.com/tpu/docs/creating-deleting-tpus.networkConfigsrM   r   z<cannot target multiple workers without the `--command` flag.O!!! This TPU is going through a maintenance event, and might be unavailable !!!Nr   :Unable to retrieve host information from guest attributes.Failed to connect to TPU.?Unable to retrieve host keys from guest attributes. Continuing.username_requestedinstance_enable_osloginr   {1}:{0} {1} z<Preparing SSH command execution; output will be logged to {}r   hostname)F	tpu_utilsSSHPreppedNodeTPUNodeGetr   IsTPUVMNoder
   BadArgumentExceptionr:   r7   r   r   StateValueValuesEnumhasattrrT   r  rv   ru   r   internal_iprt   commandr\   healthHealthValueValuesEnumUNHEALTHY_MAINTENANCEr   r'   r   r   r   r   r   r   IAP_TROUBLESHOOTING_HELPr2   IapTunnelingUnavailabler   r   r   BaseSSHCLIHelperr   r  r   GetPublicKeyToEntry
GetProjectr   r   GetSSHKeyExpirationFromArgsr   GetOsloginStater   r	   ComputeApiHolderclientr  r(   dry_runr   r[   r  r   ssh_argsextendoutput_directoryr  r   r   r   )r9   r  r   r  r   r  prepped_nodesidxr	  tpur   n_netsr   r   r   _expiration_micrososlogin_stateoutput_directory_pathru   indexr  s                         r!   PrepareNodeForSSHrG  }  s   F ))m, 	-(#	99	%$			t	$	$

)
)	D  4::s||00EExP t-..aC8K8K4L 	 ,
kk4(($*:*:F, 		 	 !A%dll

-
-F  kk				0	0	F	FG KK	 
$

 1$J\-D-D)E)J  1	l55x &  !566##	iiLM	jj23	jj/02244IIOP%)L"%J!	&L" &668,d#&&++88:BBD*"--,,, 
 %@@FA''- 4T :..}=DDMM
M  -111L ##J5*	DLLc99j :>dll0054,,	]]!!$--0	JJFMM!	
 !#,	2338O8O)) %a&e,
#
3
3UJm 
	

45

124466,9l!!&) * GG,/#	r#   c                    / nSn/ nU  H,  nUR                  UR                  R                  5       5        M.     [        U5      nS/U-  n[        R
                  R                  SR                  U[        U 5      U5      5        U  GH  nUR                  R                  5        GH  u  p[        XX5      nUR                  (       aS  [        R                  R                  SR                  UR                  UR                  R                  5      5      5        Mv  SnSnUR                  (       a/  [!        SR                  U["        R$                  " U	5      5      5      n[        UR                  5      S:  d  [        U 5      S:  a  UR'                  [(        R*                  " [,        SU	UUUR                  R                  US[.        4S	95        US
   R1                  5         US-  nUR2                  (       a  XB:X  a  [5        X85        Sn/ nGMj  GMm  GMp  [-        SU	UUUR                  R                  US[.        5        GM     GM     US:  a  U(       a  [5        X85        ggg)zSSH's into the prepped nodes.

Args:
  prepped_nodes: The list of prepared nodes to be SSHed into.
  args: The list of arguments passed in to SSH with.
  total_ssh_batch_size: The final parsed batch size to SSH into the workers'
    nodes.
r   NzWUsing ssh batch size of {}. Attempting to SSH into {} nodes with a total of {} workers.r!  z	{}/{}.logrM   SSHTtargetr   F)r<  rt   r   rT   r   r   r   r(   r  r:  r   r   Buildr   r   r=  r   rU   rV   r   	threadingThreadr   r  rq   r   r   )r>  r   total_ssh_batch_sizer   current_batch_sizert   r	  r|   r   ru   r
  r   r  rE  s                 r!   SSHIntoPreppedNodesrR  &  s    +*#ll--3356 $ 
O'&7"-**V0#m2DgN
 $l#..446t67c	chhsyy)@)@)D)DEFG"			'4cmmF6KL

 
\$$	%	)S-?!-C,! ++//&		
 	Ba((":
 
< 
+	 ; ) 	##''		
W 7 $n q[[;6 ![r#   c                     [         R                  " UR                  5      nUR                  (       a  UR                  UR                  l        O(UR                  UR                  S   R                  l        SnU R                  (       dE  UR                  R                  [        UR                  X!R                  5      U R                  S5      nSnU R                  S5      (       aM  U R                  (       a<  UR                   U   n[#        U UR$                  UR&                  U R(                  U5      n[*        R,                  " UR                  UUR.                  UU R0                  U R2                  UR4                  US9$ )aN  Prepares the SCP command used to SCP into the worker.

Args:
  args: The arguments passed in by the user.
  prepped_node: The object that contains all the necessary information to scp
    into the node.
  worker: the worker to scp into.
  ips: The ips of the worker

Returns:
  ssh.SCPCommand that can be used to execute SCP command.
r   Nr   )r   r   	recursivecompressr   r   )copydeepcopydstr   r@   hostsrcsr   r   r   r   r   r   r  r   r   r  r   r  r   r   r   
SCPCommandr   recurserU  r   )r   r	  ru   r
  
worker_dstr   r   r  s           r!   
SCPPrepCmdr^  }  s3    }}\--.* ^^J (+~~La$'	%%//loov/M/MN%%G /	2338O8O //7M)""		O 
 ..}}**%	
 	r#   c                 &    AUR                  U 5      $ )r  r  )r   r   r   s      r!   	SCPRunCmdr`    s    
	r#   c
                    [         R                  " U SX#Xx5      n
[         R                  " U5      nUR                  XR                  5      n[         R
                  " U5      (       d  [        R                  " SS5      e[        US5      (       d  SO[        UR                  5      n[        UR                  UR                  UR                  U5      U
l        [        U
R                  5      S:  a5  U
R                   S   R"                  (       a  [        R$                  " SS5      e['        UR(                  UR*                  R,                  R.                  U 5        UR0                  UR*                  R,                  R2                  R4                  :X  a  [6        R8                  " S	5        [        UR                  5      S:  =(       a    [        U
R                  5      S:H  n[;        XU
R                  XR                  5      nUc  UR=                  S
5      (       a~  UR>                  (       am  [6        R@                  " S5        [6        RB                  RE                  S5        [6        RB                  RE                  [F        5        [H        RJ                  " 5       e[6        R@                  " S5        SU
l&        O[O        UUU
R                  U5      U
l&        [P        RR                  " 5       U
l*        U
RT                  RW                  U5        U
RT                  RX                  R[                  5       R]                  5       n[         R^                  " X*RT                  5      U
l0        URb                  (       d  [P        Rd                  " U5      u  nn[f        Rh                  " SU
R`                  U	Rj                  UUUU[m        U5      [n        Rp                  " U5      Rr                  R*                  S9	nURj                  =U
l5        U	l5        SRu                  UU	Rj                  5      nURb                  (       d3  URv                  (       d"  [y        U
R`                  XXR                  U5        SU
l=        URb                  (       dd  U
RT                  RX                  R|                  U
l=        URv                  (       d.  [        U
R                  5      S:  a  [        U
Rz                  5        / U
l@        UR                  (       a%  U
R                  R                  UR                  5        0 U
lC        UR=                  S
5      (       a  UR>                  (       a  U
R                   H  nU(       a  SOUn[        UR                  US5      nUcW  [6        RB                  RE                  S5        [6        RB                  RE                  [F        5        [H        RJ                  " 5       eUU
R                  U'   M     UR                  U
lF        XU'   U
$ )a  Prepares TPU VM Node for SCP.

Args:
  tpu_name: The unqualified name of the tpu instance to prepare for SCP.
  args: The command line arguments used for SCP.
  release_track: The release track/version of client protos to use.
  enable_batching: A bool, True if the user opts into batching requests.
  username_requested: A bool, True if the user has passed a specific username
    in the args.
  prepped_nodes: The list to put resulting prepared nodes into.
  idx: The index specifying which slot in the 'prepped_nodes' list to put the
    output node.
  srcs: The list of sources for the file to send from.
  dst: The destination to put the SCP-ed file.
  remote: The remote location for the file to be SCP-ed.

Returns:
  The prepared node that is now ready for SCP.

Raises:
  BadArgumentException: If the node retrieved is not a TPU VM. Non TPU VMs are
    not supported.
  InvalidArgumentException: If there are multiple workers targeted.
  IapTunnelingUnavailable: If IAP Tunneling is not available, the node cannot
    be SCPed into.
Nr  r  r  rM   r   r   z=cannot target multiple workers while copying files to client.r  r   r  r  r  r  r   r"  )Gr#  SCPPreppedNoder%  r&  r   r'  r
   r(  r*  rT   r  rv   ru   r   r+  rt   rZ  r   r\   r:   r7   r   r   r)  r-  r.  r/  r   r'   r   r   r   r   r   r   r0  r2   r1  r   r   r   r2  r   r  r   r3  r4  r5  r   r   r6  r   r7  r  r   r	   r8  r9  r(   r:  r   r   r   r   r   scp_flagr<  r  r   r   r   )r9   r   r  r   r  r>  r?  rZ  rX  r   r	  r@  r   rA  r   r   r   rB  rC  rD  ru   rF  r  s                          r!   PrepareNodeForSCPrd    s   L ))md, 	-(#	99	%$			t	$	$

)
)	D  t-..aC8K8K4L 	 ,
kk4(($*:*:FD, 		 	 !A%,*;*;A*>*E*E

-
-G 
 4::s||00EExP kk				0	0	F	FG KK	 
$

 1$J\-D-D)E)J  1	l55x &  !566##	iiLM	jj23	jj/02244IIOP%)L"%J!	&L" &668,d#&&++88:BBD*"--,,, 
 %@@FA''- 4T :..}=DDMM
M '4&8&88L ##J<*	DLLc99j  $,	!-!8!8!=!=!F!FL <<C 7 781<|112,	]]##DMM2 ",	2338O8O)) %a&e,
#
3
3UJm 
	

45

124466,9l!!&) * GG,/#	r#   c                 N   / nSn/ nU  H,  nUR                  UR                  R                  5       5        M.     [        U5      nS/U-  n[        R
                  R                  SR                  U[        U 5      U5      5        U  GHy  nUR                  R                  5        GHV  u  p[        XX5      nUR                  (       aS  [        R                  R                  SR                  UR                  UR                  R                  5      5      5        Mv  [        UR                  5      S:  d  [        U 5      S:  a  UR                  [         R"                  " [$        SU	UUUR                  R                  SS[&        4S95        US	   R)                  5         US-  nUR*                  (       a  XB:X  a  [-        X85        Sn/ nGM&  GM)  GM,  [%        SU	UUUR                  R                  SS
[&        5        GMY     GM|     [        U5      S:  a  U(       a  [-        X85        ggg)zSCP's into the prepped nodes.

Args:
  prepped_nodes: The list of prepared nodes to be SCPed into.
  args: The list of arguments passed in to SCP with.
  total_scp_batch_size: The final parsed batch size to SCP into the nodes'
    workers.
r   NzVUsing scp batch size of {}.Attempting to SCP into {} nodes with a total of {} workers.r!  rM   SCPTrJ  rL  F)r<  rt   r   rT   r   r   r   r(   r^  r:  r   r   rM  r   r   r   rN  rO  r   r`  rq   r   r   )r>  r   total_scp_batch_sizescp_threadsrQ  rt   r	  r|   r   ru   r
  r   s               r!   SCPIntoPreppedNodesri  g  s    +*#ll--3356 $ 
O'&7"-**V0#m2DgN
 $l#..446t67c	chhsyy)@)@)D)DEFG 
\$$	%	)S-?!-C,! ++//		
 	Ba((":
 
< 
+	 ; ) 	##''		
K 7 $b 	_q[;6 )r#   )Fall)rM   )>rI   
__future__r   r   r   rV  r   r   rN  r   apitools.base.pyr   apitools.base.py.exceptionsr   r   googlecloudsdk.api_lib.computer	   googlecloudsdk.callioper
   "googlecloudsdk.command_lib.computer   r   .googlecloudsdk.command_lib.compute.tpus.tpu_vmr2   r   r#  #googlecloudsdk.command_lib.util.sshr   googlecloudsdk.corer   r   googlecloudsdk.core.util.filesr   rU   r   r0  r"   r:   r<   rv   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  rG  rR  r^  r`  rd  ri  rK   r#   r!   <module>ru     s   3 &  '  	 
   , 9 1 7 . 9 8 W L 3 / # 5 
"   HMOd&;R- - @AHV'TL#,*("	J$9N &<
~0ffRT7n7tgTN7r#   