3 \me @s&UdZddlZddlZddlZddlZddlZddlZddlmZddl m Z m Z ddl m Z ddlmZddlmZmZddlmZdd lmZeZd Zd Zd d deegeededgdgdZeeeZejeZddZddZe ee e!ddddZ"ddZ#ddZ$d"ddZ%d d!Z&dS)#z&Power State Change: Change power stateN)dedent)subputil)Cloud)Config) MetaSchema get_meta_doc) ALL_DISTROS) PER_INSTANCEa[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. Zcc_power_state_changezPower State ChangezChange 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)idnametitle descriptionZdistros frequencyZexamplesZactivate_by_schema_keysc CsnyTtjrDtjddt|g\}}|jd}tjd|}|jdStjd|SWnt k rhdSXdS)NZprocstatz-cz\d+ (\w|\.|-)+\s+(/\w.+)z/proc/%s/cmdline) rZ is_FreeBSDrstr splitlinesresearchgroupZ load_fileIOError)pidoutputZ_errlinemr+/usr/lib/python3.6/cc_power_state_change.py givecmdlineUs   r cCst|trtjd||Sd|}yjtj|t|t d}|j|j}|dkr`tjd|dS|dkrxtjd|d Stj d ||d SWn.t k r}ztj d ||d Sd}~XnXdS) NzStatic Condition: %szcheck_condition command (%s): )shellrz%sexited 0. condition met.Trz%sexited 1. condition not met.Fz*%sunexpected exit %s. do not apply change.z%sUnexpected error: %s) isinstanceboolLOGdebug subprocessPopenlist communicate returncodewarning Exception)ZcondZpreprocreterrrcheck_conditiongs&    r0)rcfgcloudargsreturnc Csy,t||j\}}}|dkr*tjddSWn0tk r\}ztjdt|dSd}~XnX|dkrttjddStj}t |}|stjddSt tj d} tjd|dj |t jt||||t|| gdS) 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 processwz#After pid %s ends, will execute: %s )load_power_statedistror$r%r,r+rosgetpidr opendevnulljoinrZfork_cbrun_after_pid_goneexecmd) rr1r2r3timeout conditionr/ZmypidcmdlineZ devnull_fprrrhandles4    rCc Cs|jd}|dkrdSt|ts(tddddg}|jd}||jkr\tddj||f|j||jd d |jd d }yt|jd d}Wn4tk r}ztd|d |WYdd}~XnX|jdd}t|t t t fstd|||fS)Nr zpower_state is not a dict.ZhaltZpoweroffZrebootmodez@z(failed to convert timeout '%s' to float.rATz2condition type %s invalid. must be list, bool, str)NNN) getr"dict TypeErrorZshutdown_options_mapr=Zshutdown_commandfloat ValueErrorrr(r#) r1r8ZpstateZmodes_okrDr3r@r/rArrrr7s2        r7cCstj|dS)N)r9_exit)ZsysexitrrrdoexitsrNc CsXd}y*tj|tj|tjd}|j||j}Wntk rJttYnXt|dS)Nr)stdinstdoutstderr) r&r'PIPEZSTDOUTr)r*r,rN EXIT_FAIL)Zexe_argsrZdata_inr.r-rrrr?s   r?c CsFd}tj|}dd}tjtjf} xtj|kr.fatalztimeout reached before %s endedz cmdline changed for %s [now: %s]zpidfile gone [%d]zIOError during wait: %szUnexpected Exception: %sg?z&Unexpected error in run_after_pid_gonez0Unexpected Exception when checking condition: %s) timeerrnoENOENTZESRCHr rr,Zsleepr$r%r0) rZ pidcmdliner@rAfuncr3rTZend_timerUZ known_errnosrBZioerrr/rrrr>s<         r>)NN)'__doc__rWZloggingr9rr&rVtextwraprZ cloudinitrrZcloudinit.cloudrZcloudinit.configrZcloudinit.config.schemarrZcloudinit.distrosr Zcloudinit.settingsr rrSZMODULE_DESCRIPTIONmetaZ getLogger__name__r$r r0rr(rCr7rNr?r>rrrrsH      $&