o
    `۷i                     @   s  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 d dl	m
Z
 d dlmZmZmZmZ d dlZd dlmZ d dlmZmZ d dlmZmZmZ d dlmZmZmZmZmZ d d	l m!Z! d d
l"m#Z#m$Z$m%Z% d dl&m'Z' e(e)Z*dZ+ej,-ej,.ej,/e0dZ1dZ2dZ3dddZ4dd Z5dd Z6dd Z7de8fddZ9de:dee:e;f fddZ<dd  Z=G d!d" d"Z>G d#d$ d$e'Z?G d%d& d&e'Z@dS )'    N)getuserquote)DictListOptionalTuple)%DEFAULT_OBJECT_STORE_MAX_MEMORY_BYTES)cf
cli_logger)AUTOSCALER_NODE_SSH_INTERVAL_SAUTOSCALER_NODE_START_WAIT_S&DEFAULT_OBJECT_STORE_MEMORY_PROPORTION)check_bind_mounts_cmdcheck_docker_imagecheck_docker_running_cmddocker_start_cmdswith_docker_exec)LogTimer)ProcessRunnerErroris_output_redirectedrun_cmd_redirected)CommandRunnerInterface
   z_kubernetes/kubectl-rsync.sh      T)use_login_shellssilent_rsyncc                   C      t d S )Nr   _config r!   r!   \/home/ubuntu/vllm_env/lib/python3.10/site-packages/ray/autoscaler/_private/command_runner.pyis_rsync_silent1      r#   c                 C      | t d< dS )zChoose whether to silence rsync output.

    Most commands will want to list rsync'd files themselves rather than
    print the default rsync spew.
    r   Nr   valr!   r!   r"   set_rsync_silent5   s   r(   c                   C   r   )Nr   r   r!   r!   r!   r"   is_using_login_shells>   r$   r)   r'   c                 C   r%   )a  Choose between login and non-interactive shells.

    Non-interactive shells have the benefit of receiving less output from
    subcommands (since progress bars and TTY control codes are not printed).
    Sometimes this can be significant since e.g. `pip install` prints
    hundreds of progress bar lines when downloading.

    Login shells have the benefit of working very close to how a proper bash
    session does, regarding how scripts execute and how the environment is
    setup. This is also how all commands were ran in the past. The only reason
    to use login shells over non-interactive shells is if you need some weird
    and non-robust tool to work.

    Args:
        val: If true, login shells will be used to run all commands.
    r   Nr   r&   r!   r!   r"   set_using_login_shellsB   s   r*   cmdenvironment_variablesc                 C   sP   g }|  D ]\}}tj|dd}d|t|}|| qd|}||  S )a7  Prepend environment variables to a shell command.

    Args:
        cmd: The base command.
        environment_variables (Dict[str, object]): The set of environment
            variables. If an environment variable value is a dict, it will
            automatically be converted to a one line yaml string.
    ),:)
separatorszexport {}={}; )itemsjsondumpsformatr   appendjoin)r+   r,   
as_stringskeyr'   sall_varsr!   r!   r"   _with_environment_variablesV   s   

r;   c                 C   s   d|  d}ddddt |gS )NzEsource ~/.bashrc; export OMP_NUM_THREADS=1 PYTHONWARNINGS=ignore && ()bashz--loginz-c-ir   )r+   force_interactiver!   r!   r"   _with_interactivei   s
   r@   c                   @   s$   e Zd ZdddZddddZdS )	
SSHOptionsNc                 K   sV   || _ dtjddddd| _|r#tjdkrn| jdd|d	d
 | j| d S )Nnoyesr   r   )StrictHostKeyCheckingUserKnownHostsFileIdentitiesOnlyExitOnForwardFailureServerAliveIntervalServerAliveCountMaxwin32autoz{}/%C10s)ControlMasterControlPathControlPersist)ssh_keyosdevnullarg_dictsysplatformupdater4   )selfrP   control_pathkwargsr!   r!   r"   __init__r   s$   
zSSHOptions.__init__<   timeoutc                C   sF   d || jd< | jrd| jgng }|dd dd | j D D  S )Nz{}sConnectTimeoutr>   c                 S      g | ]	}|D ]}|qqS r!   r!   ).0yxr!   r!   r"   
<listcomp>   s    z2SSHOptions.to_ssh_options_list.<locals>.<listcomp>c                 s   s,    | ]\}}|d urdd ||gV  qd S )Nz-oz{}={}r4   )r`   kvr!   r!   r"   	<genexpr>   s    z1SSHOptions.to_ssh_options_list.<locals>.<genexpr>)r4   rS   rP   r1   )rW   r]   ssh_key_optionr!   r!   r"   to_ssh_options_list   s   zSSHOptions.to_ssh_options_listN)__name__
__module____qualname__rZ   ri   r!   r!   r!   r"   rA   q   s    
$rA   c                   @   s   e Zd Zdd Zdd Zdd Zdd Z						d&d
ee de	de	de	fddZ
														d'dee dede	deeeeef   de	deeeef  dedede	de	defddZdd Zd(d d!Zd(d"d#Zd$d% ZdS ))SSHCommandRunnerc                 C   s   t |  }t t   }	tjdkrd }
nd|	d t |d t }
|| _	|| _
|| _|| _|| _|| _|d| _|d | _|
| _d | _|dd | _t| j| j| jd| _d S )NrJ   z/tmp/ray_ssh_{}/{}ssh_private_keyssh_userssh_proxy_commandProxyCommand)hashlibsha256encode	hexdigestr   rT   rU   r4   HASH_MAX_LENGTHcluster_name
log_prefixprocess_runnernode_iduse_internal_ipprovidergetro   rp   ssh_control_pathssh_iprq   rA   ssh_options)rW   rz   r|   r~   auth_configry   r{   r}   ssh_control_hashssh_user_hashr   r!   r!   r"   rZ      s.   

zSSHCommandRunner.__init__c                 C   s"   | j r
| j| jS | j| jS rj   )r}   r~   internal_ipr|   external_iprW   r!   r!   r"   _get_node_ip   s   zSSHCommandRunner._get_node_ipc                 C   s  |   }|d urtd| |S t}tdb t |k ra| j| jsi|   }|d ur<td| |W  d    S t	dt
t| t| t |k rq| j| jr%W d    d S W d    d S W d    d S W d    d S 1 s|w   Y  d S )Nz
Fetched IPzWaiting for IPReceivedz)Not yet available, retrying in {} seconds)r   r   labeled_valuer   grouptimer~   is_terminatedr|   printr
   boldstrsleep)rW   deadlineipintervalr!   r!   r"   _wait_for_ip   sD   




zSSHCommandRunner._wait_for_ipc              
   C   s   | j d urd S t t }t| jd  | |}t|d ud |d us*J dW d    n1 s4w   Y  || _ | jd urizt	j
| jddd W d S  tyh } ztdt| W Y d }~d S d }~ww d S )NzGot IPzCould not get node IP.zUnable to find IP of nodei  T)modeexist_okz{})r   r   r   r   rz   r   r   doassertr   rQ   makedirsOSErrorwarningr   )rW   r   r   er!   r!   r"   _set_ssh_ip_if_required   s"   


z(SSHCommandRunner._set_ssh_ip_if_requiredF	final_cmdwith_outputexit_on_failsilentc              
   C   s   zcz*|st || j|t dW W tj  tj  S | j|W W tj  tj  S  tj	yc } z+d
|}t sEtdd|j|d|rPtd|dd}t rY|d	7 }t|dd}~ww tj  tj  w )
a  Run a command that was already setup with SSH and `bash` settings.

        Args:
            final_cmd (List[str]):
                Full command to run. Should include SSH options and other
                processing that we do.
            with_output (bool):
                If `with_output` is `True`, command stdout will be captured and
                returned.
            exit_on_fail (bool):
                If `exit_on_fail` is `True`, the process will exit
                if the command fails (exits with a code other than 0).
            silent: If true, the command output will be silenced.

        Raises:
            ProcessRunnerError: If using new log style and disabled
                login shells.
            click.ClickException: If using login shells.
        )r{   r   r    zCommand failedssh_command_failed)codecommandzCommand failed:

  {}
NzSSH command failed.z+ See above for the output from the failure.)r   r{   r)   rT   stdoutflushstderrcheck_output
subprocessCalledProcessErrorr6   r   
returncodeclickClickExceptionr4   r   )rW   r   r   r   r   r   
joined_cmdfail_msgr!   r!   r"   _run_helper   sH   



zSSHCommandRunner._run_helperNx   rK   r0   r+   r]   port_forwardr,   run_envssh_options_override_ssh_keyshutdown_after_runreturnc              	   C   s  |	r|d7 }|r| j rt|| j d}nt|}n| j}t|ts)J dt||   t r5ddg}ndg}|rut	d. t|t
sH|g}|D ]\}}tdt|t| |dd	||g7 }qJW d    n1 spw   Y  ||j|d
 d| j| jg }|r|rt||}t r|t|7 }n||g7 }n|d tdt| t  tdtd| W d    n1 sw   Y  tjdkrt  | j||||
dW  d    S 1 sw   Y  d S | j||||
dS )N; sudo shutdown -h nowrr   z.ssh_options must be of type SSHOptions, got {}sshz-ttzForwarding portsz+Forwarding port {} to port {} on localhost.z-Lz{}:localhost:{}r\   z{}@{}z while true; do sleep 86400; doneRunning `{}`zFull command is `{}`r   r   r   )rq   rA   r   
isinstancer4   typer   r)   r   r   listverboser
   r   ri   rp   r   r;   r@   r5   indentedvery_verboser6   	verbosityr   )rW   r+   r]   r   r   r   r,   r   r   r   r   r   r   localremoter   r!   r!   r"   run@  sr   








$zSSHCommandRunner.runc                 C   sJ   | dpg }| dpg }dd |D }dd |D }dd || D S )Nrsync_excludersync_filterc                 S   s   g | ]}d |gqS )z	--excluder!   )r`   r   r!   r!   r"   rc     s    z>SSHCommandRunner._create_rsync_filter_args.<locals>.<listcomp>c                 S   s   g | ]	}d d |gqS )z--filterzdir-merge,- {}rd   )r`   r   r!   r!   r"   rc     s    c                 S   r_   r!   r!   )r`   	args_listargr!   r!   r"   rc     s    )r   )rW   optionsrsync_excludesrsync_filtersexclude_argsfilter_argsr!   r!   r"   _create_rsync_filter_args  s   z*SSHCommandRunner._create_rsync_filter_argsc                 C   s   |    |pi }tjdkr(ddg}|| jjdd7 }||d| j| j|g7 }n.dg}|dt	d	g| jjdd g7 }|d
g7 }|| j
|d7 }||d| j| j|g7 }tdtd| | j|t d d S NrJ   scpz-rr   r\   z{}@{}:{}rsyncz--rshr   z-avzr   r   r   r   r   rT   rU   r   ri   r4   rp   r   r   list2cmdliner   r   r   r
   r   r6   r   r#   rW   sourcetargetr   r   r!   r!   r"   run_rsync_up  s$   

zSSHCommandRunner.run_rsync_upc                 C   s   |    tjdkr$ddg}|| jjdd7 }|d| j| j||g7 }n.dg}|dt	d	g| jjdd g7 }|d
g7 }|| j
|d7 }|d| j| j||g7 }tdtd| | j|t d d S r   r   r   r!   r!   r"   run_rsync_down  s"   

zSSHCommandRunner.run_rsync_downc                 C   s*   | j rd| j | j| jS d| j| jS )Nz&ssh -o IdentitiesOnly=yes -i {} {}@{}
z ssh -o IdentitiesOnly=yes {}@{}
)ro   r4   rp   r   r   r!   r!   r"   remote_shell_command_str  s   z)SSHCommandRunner.remote_shell_command_str)FFF)
Nr   FNFNrK   r0   FFrj   )rk   rl   rm   rZ   r   r   r   r   r   boolr   r   intr   r   objectr   r   r   r   r   r!   r!   r!   r"   rn      sl    &
B	

P

rn   c                   @   s2  e Zd Zdd Z									d1dee d	ed
edeee	eef   dedee
eef  dedededefddZd2ddZd2ddZdd Zdd Zdd Zd3ddZd ed!e
eef defd"d#Zd$ed%e
eef d&efd'd(Zd)ee dee fd*d+Zd)ee dee fd,d-Zd.edefd/d0ZdS )4DockerCommandRunnerc                 K   sP   t di || _|d | _|| _d | _d| _|dd}|r#d| _d S d| _d S )Ncontainer_nameF
use_podmanpodmandockerr!   )rn   ssh_command_runnerr   docker_confighome_dirinitializedr   
docker_cmd)rW   r   common_argsr   r!   r!   r"   rZ     s   
zDockerCommandRunner.__init__Nr   FrK   r0   r+   r]   r   r   r   r,   r   r   r   r   c
           
      C   s   |dkrt |r|| jdkrdn| j}|rt||}|| jkr@| j|dd}t r2dt|}t|g| j	t | jdd }|	rF|d7 }| j
j||||||d	S )
NrK   r   hostT)any_charr   r   with_interactiver   r   )r]   r   r   r   r   )r   findr   r;   _docker_expand_userr)   r6   r@   r   r   r   r   )
rW   r+   r]   r   r   r   r,   r   r   r   r!   r!   r"   r     s>   

zDockerCommandRunner.runc              
   C   s.  |pi }t j| | jj|d}t j|d}t	j
dkr3|dd}|dd}|dd}| jjd| d| jj d| t d | jj|||d |  r|d	d
st j|rd|d7 }tdt j| |g| jt | jdd }| jjd|| j|| j| |t d d S d S d S )N/rJ   \	mkdir -p  && chown -R r   r   r   docker_mount_if_possibleFz/.zmkdir -p {}r   r   z){} && rsync -e '{} exec -i' -avz {} {}:{})rQ   pathr6   _get_docker_host_mount_locationr   ry   lstripdirnamerstriprT   rU   replacer   rp   r#   r   _check_container_statusr   isdirr   r4   r   r   r)   r   )rW   r   r   r   host_destinationhost_mount_locationprefixr!   r!   r"   r     s\   
	
z DockerCommandRunner.run_rsync_upc              
   C   s   |pi }t j| | jj|d}t j|d}|	dd}| jj
d| d| jj d| t d |d dkr@|d7 }|d	d
s^| jj
d| j| j| ||	ddt d | jj|||d d S )Nr   r   r   r   r   r   .r   Fz,rsync -e '{} exec -i' -avz --delete {}:{} {}r   )rQ   r   r6   r   r   ry   r   r   r   r   r   rp   r#   r   r4   r   r   r   r   )rW   r   r   r   host_sourcer   host_mount_location_unixr!   r!   r"   r   I  s<   z"DockerCommandRunner.run_rsync_downc                 C   s.   | j  dddd}|d| j| j S )Nr   zssh -tt   
z {} exec -it {} /bin/bash
)r   r   r   stripr4   r   r   )rW   	inner_strr!   r!   r"   r   k  s   
z,DockerCommandRunner.remote_shell_command_strc                 C   s   d}| j jd| j d| ddd}|  }||v s d|vrF| jdkr*g d}nd	d
g}t| j  d| j  dd|  d S d S )NNoExistzcommand -v z
 || echo ''Tr   r   )z2curl -fsSL https://get.docker.com -o get-docker.shzsudo sh get-docker.shzsudo usermod -aG docker $USERz sudo systemctl restart docker -fzsudo apt-get updatezsudo apt-get -y install podmanz  not installed. You can install z@ by adding the following commands to 'initialization_commands':
r  )	r   r   r   decoder  loggererror
capitalizer6   )rW   no_existoutputcleaned_outputinstall_commandsr!   r!   r"   _check_docker_installedu  s&   

z+DockerCommandRunner._check_docker_installedc                 C   sF   | j rdS | jjt| j| jddd }d| v o"d| vS )NTr  utf-8truezno such object)	r   r   r   r   r   r   r  r  lower)rW   r  r!   r!   r"   r     s   	z+DockerCommandRunner._check_container_statusc                 C   s~   | d}|dkr=| jd u r$| jj| j d| j dddd | _|r/|d| jd	 S |s=|d
kr=|d| jdS |S )N~r  z exec z printenv HOMETr  r  z~/r   r   r  )	r   r   r   r   r   r   r  r  r   )rW   stringr   user_posr!   r!   r"   r     s   


z'DockerCommandRunner._docker_expand_userimagecleaned_bind_mountsc           
         s   d} j t j jdddd }||kr!td j||  j t j jdddd }z+t	
|}dd |D } fd	d| D }|| }	|	r\d}td
|	 W |S W |S  t	jyn   td Y |S w )NFTr   )r   r   r  z[A container with name {} is running image {} instead of {} (which was provided in the YAML)c                 S   s   h | ]	}|d   dqS )Destinationr   )r  )r`   mntr!   r!   r"   	<setcomp>  s    zLDockerCommandRunner._check_if_container_restart_is_needed.<locals>.<setcomp>c                    s   h | ]
}  |d qS )r   )r   r  )r`   r   r   r!   r"   r    s    z~This Docker Container is already running. Restarting the Docker container on this node to pick up the following file_mounts {}z`Unable to check if file_mounts specified in the YAML differ from those on the running container.)r   r   r   r   r  r  r   r  r   r2   loadskeysr   JSONDecodeErrorr   )
rW   r  r  re_init_requiredrunning_imagemountsactive_mountsactive_remote_mountsrequested_remote_mountsunfulfilled_mountsr!   r   r"   %_check_if_container_restart_is_needed  s`   		

z9DockerCommandRunner._check_if_container_restart_is_neededas_headfile_mountssync_run_yetc                C   sB  ddg}| j |rdnd d| j d}|   | j ddr4|s'J d	| jd
| j|dd n| | j d| d| j d|  | }|D ]}||d  qLd}|  }	d}
|	r}| 	||}
|
r}| j d| j
 }td| | j|dd |	r|
r|sdS | jj| j dd | dd  }d}zt|D ]}|dr|dd } nqW n tjy } z
td|  |d }~ww | j dg | j |rdnd dg  }t| jj||| j
| | || jj|| j}| j|dd d}|D ]}||v r|s| || | | jdj| jtj|  | jj|!dd| j
| "|d z| d | d!|  W q t#y   | jd"| ddd# }|dd$ }|dd% }|dd& }| jd'ddd# }t$d(| d)| d*| d+| d,| d-| d| d. Y qw qd| _%|S )/Nz~/ray_bootstrap_config.yamlz~/ray_bootstrap_key.pemheadworker_imager  pull_before_runTz@Image must be included in config if pull_before_run is specifiedz
{} pull {}r   )r   z image inspect z 1> /dev/null  2>&1 || z pull Fz stop zExecuting Docker command: %sr   z"inspect -f '{{json .Config.Env}}' r  z/rootzHOME=r  zHUnable to deserialize `image_env` to Python object. The `image_env` is:
run_options_run_optionsz5rsync -e '{cmd} exec -i' -avz {src} {container}:{dst}r   r   )r+   src	containerdstzcat z1 >/dev/null 2>&1 || sudo chown $(id -u):$(id -g) zls -l r  r      r   whoamizFile (z) is owned by user:z and group:z with permissions (z). The current user (z) does not have permission to read these files, and Ray may not be able to autoscale. This can be resolved by installing `sudo` in your container, or adding a command like 'chown z' to your `setup_commands`.)&r   r   r  r   r4   r   copypopr   r*  r   r  infor   r  r  r2   r   
startswithsplitr"  r   r  r   rp   _configure_runtime_auto_configure_shmry   r   rQ   r   r6   r   r   r   	Exceptionr   r   )rW   r+  r,  r-  BOOTSTRAP_MOUNTSspecific_imager  r  docker_run_executedcontainer_runningrequires_re_initdocker_stop_cmd	image_envhome_directoryenv_varr   user_docker_run_optionsstart_commandmount
lsl_stringpermissionsownerr   current_userr!   r!   r"   run_init  s  






4zDockerCommandRunner.run_initr2  c              
   C   s   | j dr|S | jj| j dd dd  }d|v rNz| jjddd |d	g W S  tyM } zt	d
 t
d|  |W  Y d }~S d }~ww |S )N#disable_automatic_runtime_detectionr   zinfo -f '{{.Runtimes}}' Tr  znvidia-container-runtimez
nvidia-smiFz--runtime=nvidiaz7NVIDIA Container Runtime is present, but no GPUs found.znvidia-smi error: )r   r   r   r   r   r  r  r@  r  r   debug)rW   r2  runtime_outputr   r!   r!   r"   r>    s*   z&DockerCommandRunner._configure_runtimec              
   C   s   | j dr|S |D ]}d|v rtd|  |  S q
z5| jjddd  }tdd |	d	D d
 	 d }|d }t
|t d t}|d| dg W S  tyn } ztd|  |W  Y d }~S d }~ww )Ndisable_shm_size_detectionz
--shm-sizez;Bypassing automatic SHM-Detection because of `run_option`: zcat /proc/meminfo || trueTr  c                 S   s   g | ]}d |v r|qS )MemAvailabler!   )r`   lnr!   r!   r"   rc     s    z;DockerCommandRunner._auto_configure_shm.<locals>.<listcomp>r  r   r  i   g?z--shm-size='zb'z5Received error while trying to auto-compute SHM size )r   r   r  r;  r   r   r  r  r   r=  minr   r	   r@  r   )rW   r2  run_opt
shm_outputavailable_memoryavailable_memory_bytesshm_sizer   r!   r!   r"   r?    sH   
z'DockerCommandRunner._auto_configure_shmry   c                 C   s   ddl m} ||S )z0Return the docker host mount directory location.r   )get_docker_host_mount_location)ray.autoscaler.sdkr^  )rW   ry   r^  r!   r!   r"   r     s   z3DockerCommandRunner._get_docker_host_mount_location)	Nr   FNFNrK   r0   Frj   )F)rk   rl   rm   rZ   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   r*  rQ  r>  r?  r   r!   r!   r!   r"   r     sp    	


/
4"



8

 "r   )Art   r2   loggingrQ   r   rT   r   getpassr   shlexr   typingr   r   r   r   r   ray._private.ray_constantsr	   "ray.autoscaler._private.cli_loggerr
   r   !ray.autoscaler._private.constantsr   r   r   ray.autoscaler._private.dockerr   r   r   r   r   !ray.autoscaler._private.log_timerr   .ray.autoscaler._private.subprocess_output_utilr   r   r   ray.autoscaler.command_runnerr   	getLoggerrk   r  rx   r   r6   r   abspath__file__KUBECTL_RSYNCMAX_HOME_RETRIESHOME_RETRY_DELAY_Sr    r#   r(   r)   r   r*   r   r   r;   r@   rA   rn   r   r!   r!   r!   r"   <module>   sJ    

	3  9