
­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
3
\me              	   @   s&  U d 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
mZ ddlmZ ddlmZ ddlmZmZ ddlmZ dd	lmZ eZd
ZdZdddeegeededgdgdZeeeZ ejeZdd Zdd Ze eee!ddddZ"dd Z#dd Z$d"ddZ%d d! Z&dS )#z&Power State Change: Change power state    N)dedent)subputil)Cloud)Config)
MetaSchemaget_meta_doc)ALL_DISTROS)PER_INSTANCE   a[  This module handles shutdown/reboot after all config modules have been run. By
default it will take no action, and the system will keep running unless a
package installation/upgrade requires a system reboot (e.g. installing a new
kernel) and ``package_reboot_if_required`` is true.

Using this module ensures that cloud-init is entirely finished with
modules that would be executed.

An example to distinguish delay from timeout:

If you delay 5 (5 minutes) and have a timeout of
120 (2 minutes), then the max time until shutdown will be 7 minutes, though
it could be as soon as 5 minutes. Cloud-init will invoke 'shutdown +5' after
the process finishes, or when 'timeout' seconds have elapsed.

.. note::
    With Alpine Linux any message value specified is ignored as Alpine's halt,
    poweroff, and reboot commands do not support broadcasting a message.

Zcc_power_state_changezPower State ChangezChange power statez            power_state:
                delay: now
                mode: poweroff
                message: Powering off
                timeout: 2
                condition: true
            z            power_state:
                delay: 30
                mode: reboot
                message: Rebooting machine
                condition: test -f /var/tmp/reboot_me
            power_state)idnametitledescriptionZdistros	frequencyZexamplesZactivate_by_schema_keysc             C   sn   yTt j rDtjddt| g\}}|j d }tjd|}|jdS t jd|  S W n t	k
rh   d S X d S )NZprocstatz-c   z\d+ (\w|\.|-)+\s+(/\w.+)   z/proc/%s/cmdline)
r   Z
is_FreeBSDr   str
splitlinesresearchgroupZ	load_fileIOError)pidoutputZ_errlinem r   +/usr/lib/python3.6/cc_power_state_change.pygivecmdlineU   s    
r    c             C   s   t | trtjd|  | S d|  }yjtj| t | t d}|j  |j}|dkr`tjd| dS |dkrxtjd| d	S tj	d
|| d	S W n. t
k
r } ztj	d|| d	S d }~X nX d S )NzStatic Condition: %szcheck_condition command (%s): )shellr   z%sexited 0. condition met.Tr   z%sexited 1. condition not met.Fz*%sunexpected exit %s. do not apply change.z%sUnexpected error: %s)
isinstanceboolLOGdebug
subprocessPopenlistcommunicate
returncodewarning	Exception)ZcondZpreprocreter   r   r   check_conditiong   s&    
r0   )r   cfgcloudargsreturnc       
      C   s   y,t ||j\}}}|d kr*tjd d S W n0 tk
r\ } ztjdt| d S d }~X nX |dkrttjd d S tj }t	|}|stjd d S t
tjd}	tjd|dj| tjt||||t||	g d S )	Nz&no power_state provided. doing nothingz%%s Not performing power state change!Fz3Condition was false. Will not perform state change.z5power_state: failed to get cmdline of current processwz#After pid %s ends, will execute: %s )load_power_statedistror$   r%   r,   r+   r   osgetpidr    opendevnulljoinr   Zfork_cbrun_after_pid_goneexecmd)
r   r1   r2   r3   timeout	conditionr/   ZmypidcmdlineZ
devnull_fpr   r   r   handle   s4    


rC   c       	      C   s   | j d}|d krdS t|ts(tddddg}|j d}||jkr\tddj||f |j||j d	d
|j dd}yt|j dd}W n4 tk
r } ztd|d  |W Y d d }~X nX |j dd}t|t	t
tfstd|||fS )Nr   zpower_state is not a dict.ZhaltZpoweroffZrebootmodez<power_state[mode] required, must be one of: %s. found: '%s'.,delayZnowmessage)rD   rF   rG   r@   g      >@z(failed to convert timeout '%s' to float.rA   Tz2condition type %s invalid. must be list, bool, str)NNN)getr"   dict	TypeErrorZshutdown_options_mapr=   Zshutdown_commandfloat
ValueErrorr   r(   r#   )	r1   r8   ZpstateZmodes_okrD   r3   r@   r/   rA   r   r   r   r7      s2    





r7   c             C   s   t j|  d S )N)r9   _exit)Zsysexitr   r   r   doexit   s    rN   c             C   sX   d}y*t j| t j|t jd}|j| |j}W n tk
rJ   tt Y nX t| d S )Nr   )stdinstdoutstderr)	r&   r'   PIPEZSTDOUTr)   r*   r,   rN   	EXIT_FAIL)Zexe_argsr   Zdata_inr.   r-   r   r   r   r?      s    


r?   c             C   sF  d }t j  | }dd }tjtjf}	xt j  |kr<d|  }P y"t| }
|
|kr\d| |
f }P W nr tk
r } z*|j|	krd|j }n|d|  P W Y d d }~X n. tk
r } z|d|  W Y d d }~X nX t jd q&W |s|d	 tj	| yt
|sd S W n0 tk
r8 } z|d
|  W Y d d }~X nX ||  d S )Nc             S   s   t j|  tt d S )N)r$   r+   rN   rS   )msgr   r   r   fatal   s    
z!run_after_pid_gone.<locals>.fatalztimeout reached before %s endedz cmdline changed for %s [now: %s]zpidfile gone [%d]zIOError during wait: %szUnexpected Exception: %sg      ?z&Unexpected error in run_after_pid_gonez0Unexpected Exception when checking condition: %s)timeerrnoENOENTZESRCHr    r   r,   Zsleepr$   r%   r0   )r   Z
pidcmdliner@   rA   funcr3   rT   Zend_timerU   Zknown_errnosrB   Zioerrr/   r   r   r   r>      s<    


r>   )NN)'__doc__rW   Zloggingr9   r   r&   rV   textwrapr   Z	cloudinitr   r   Zcloudinit.cloudr   Zcloudinit.configr   Zcloudinit.config.schemar   r   Zcloudinit.distrosr	   Zcloudinit.settingsr
   r   rS   ZMODULE_DESCRIPTIONmetaZ	getLogger__name__r$   r    r0   r   r(   rC   r7   rN   r?   r>   r   r   r   r   <module>   sH   
$&
