
    p
f                     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	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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mZ d d
lmZ d dl m!Z! d dl"m#Z#m$Z$m%Z% d dl&m'Z' ddgZ(	  e
jR                  d      Z* e!d      Z+d Z,d Z-d Z.d Z/d Z0d Z1d Z2d Z3dZ4 e
jR                  d      Z5 e
jR                  d      Z6da7dZ8dZ9 e
jR                  d e
jt                        Z;d!Z<d"Z=d#Z>d$Z? e
jR                  d%      Z@d&ZAd'ZB G d( d)eC      ZDy)*    Ngetpwall)conf)logger)fileutil)	shellutil)textutil)OSUtilError)ustrarray_to_bytes)	CryptUtil)FlexibleVersion)
RouteEntryNetworkInterfaceCardAddFirewallRules)CommandErrorz3/lib/udev/rules.d/75-persistent-net-generator.rulesz)/etc/udev/rules.d/70-persistent-net.rulesz^[^\d\.]*([\d\.]+).*$z1.4.21c                 .    | r|j                  dd       |S )zY
    If 'wait' is True, adds the wait option (-w) to the given iptables command line
       -w)insert)waitcommands     G/usr/lib/python3/dist-packages/azurelinuxagent/common/osutil/default.py	_add_waitr   A   s     q$N    c                  
    ddgS )Niptablesz	--version r   r   r   get_iptables_version_commandr   J   s    $$r   c                     t        | g d      S )N)r   -tsecurity-L-nxvr   r   s    r   get_firewall_list_commandr'   N   s    TGHHr   c                     t        | g d      S )N)r   r!   r"   r#   OUTPUTz--zeror)   r$   r%   r&   s    r   get_firewall_packets_commandr*   R   s    Teffr   c                 T    t        | dddt        j                  dd|dddd	d
dddg      S )Nr   r!   r"   r)   -d-ptcp-m	conntrack	--ctstateINVALID,NEW-jACCEPTr   r   DELETE_COMMANDr   destinations     r   ,get_firewall_delete_conntrack_accept_commandr9   X   sO    T $
4D4S4SU]_ceprvx}  @D  FQ!=$BC Cr   c                 N    t        j                  t         j                  ||       S )Nr&   )r   get_accept_tcp_ruler6   r7   s     r   get_delete_accept_tcp_ruler<   ^   s     //0@0O0OQ\cghhr   c                 f    t        | dddt        j                  dd|dddd	d
t        |      ddg      S )Nr   r!   r"   r)   r,   r-   r.   r/   ownerz--uid-ownerr3   r4   )r   r   r6   str)r   r8   	owner_uids      r   (get_firewall_delete_owner_accept_commandrA   b   sV    TJj:J:Y:Y[ceikvx|  D  FJ  LS)3y>4K L Lr   c                 T    t        | dddt        j                  dd|dddd	d
dddg      S )Nr   r!   r"   r)   r,   r-   r.   r/   r0   r1   r2   r3   DROPr5   r7   s     r   *get_firewall_delete_conntrack_drop_commandrD   g   sO    T $
4D4S4SU]_ceprvx}  @D  FQ!=$@A Ar   z'^\s*(\d+)\s+(\d+)\s+DROP\s+.*{0}[^\d]*$z^cpu .*z^Mem.*Tzdmidecode --string system-uuidz/sys/class/dmi/id/product_uuidz5^\s*[A-F0-9]{8}(?:\-[A-F0-9]{4}){3}\-[A-F0-9]{12}\s*$i  i  i'     z^\d+:\s+(\w+):\s+(.*)$z/sys/bus/vmbus/devices/z$f8b3781a-1e82-4818-a1c3-63d806ec15bbc                      e Zd Zd Zed        Zed        Zed        ZdhdZd Z	d Z
d	 Zd
 Zd ZdhdZed        Zd Zd Zd Zed        Zd ZdidZdjdZd ZdkdZd Zed        Zd Zd Zd Zd Zd Zd Z d Z!dld Z"	 	 	 	 	 dmd!Z#dnd"Z$dod#Z%d$ Z&d% Z'dpd&Z(dqd'Z)dod(Z*d) Z+dhd*Z,dhd+Z-d, Z.d- Z/ed.        Z0d/ Z1d0 Z2ed1        Z3ed2        Z4ed3        Z5d4 Z6d5 Z7d6 Z8d7 Z9ed8        Z:d9 Z;d: Z<d; Z=d< Z>d= Z?d> Z@d? ZAd@ ZBdA ZCdB ZDdC ZEdD ZFdE ZGdF ZHdG ZIdH ZJedI        ZKedhdJ       ZLdK ZMdL ZNdM ZOdrdNZPdO ZQdP ZRdQ ZSdR ZTedS        ZUedT        ZVdU ZWdV ZXdW ZYedX        ZZdY Z[dZ Z\d[ Z]d\ Z^d] Z_e`d^        Zaed_        Zbed`        Zceda        ZddsdbZeedc        Zfedd        Zgedode       Zhedtdf       Ziedhdg       Zjy)uDefaultOSUtilc                 f    d| _         d | _        d| _        d| _        | j	                         | _        y )Nz/etc/waagent.confF)agent_conf_file_pathselinuxdisable_route_warningjit_enabledget_service_nameservice_nameselfs    r   __init__zDefaultOSUtil.__init__   s2    $7!%*"  113r   c                       y)Nwaagentr   r   r   r   rM   zDefaultOSUtil.get_service_name   s    r   c                       y)Nz/lib/systemd/systemr   r   r   r   "get_systemd_unit_file_install_pathz0DefaultOSUtil.get_systemd_unit_file_install_path   s    $r   c                       y)Nz	/usr/sbinr   r   r   r   get_agent_bin_pathz DefaultOSUtil.get_agent_bin_path   s    r   Nc                    t         sy	 | j                         }	 t        j                  t	        |            }t        j                  t        j                  |            }|j                  d      D ]1  }|j                  |      }|t        |j                  d            c S  	 y# t        $ r\}t        |t              r#|j                   dk(  s|j                   dk(  rY d }~yt#        j$                  dt'        |             Y d }~yd }~ww xY w# t        $ r9}da t#        j$                  d	j                  t'        |                   Y d }~yd }~ww xY w)
Nr   
r         z#Failed to get firewall packets: {0}Fz.Unable to retrieve firewall packets dropped{0})_enable_firewallget_firewall_will_waitr   run_commandr*   recompilePACKET_PATTERNformatsplitmatchintgroup	Exception
isinstancer   
returncoder   warnr   )rP   dst_ipr   outputpatternlinemes           r   get_firewall_dropped_packetsz*DefaultOSUtil.get_firewall_dropped_packets   s     	..0D"../KD/QR**^%:%:6%BC"LL. /Dd+A}"1771:./   a.ALLA4EYZIZ A47K  	$KK $fT!Wo/		sS   D A-B' B' $B' '	D0.DD #DD DD 	E/EEc                    	 t        j                  t                     }t        j                  |      }|1dj	                  |      }t        j                  |       t        |      t        |j                  d            t        k\  rd}|S d}|S # t        $ r?}dj	                  t        |            }t        j                  |       t        |      d }~ww xY w)Nz,Unable to determine version of iptables: {0}z0iptables did not return version information: {0}r   r    )r   r_   r   rh   rc   r   r   rk   _IPTABLES_VERSION_PATTERNre   r   rg   _IPTABLES_LOCKING_VERSION)rP   rm   rq   msgrp   r   s         r   r^   z$DefaultOSUtil.get_firewall_will_wait   s    	!**+G+IJF &++F39DKKFSCKKC.  qwwqz*.GG    	   	!@GGQPCKKC. 	!s   B 	C:CCc                     t        dd      D ]  }	 t        j                  |      } y# t        $ rH}|j                  dk(  rY d}~ y|j                  dk(  rt        dj                  |            Y d}~hd}~ww xY w)z
        Continually execute the delete operation until the return
        code is non-zero or the limit has been reached.
        r   d   N   z$invalid firewall deletion rule '{0}')ranger   r_   r   rj   rh   rc   )rP   ruleircrq   s        r   _delete_rulezDefaultOSUtil._delete_rule   s}    
 q# 	YAY**40	Y   Y<<1$<<1$#$J$Q$QRV$WXX %Ys   )	A:A5)A55A:c                 x   t         sy	 | j                  t        ||             | j                  t        ||             | j                  t	        |||             | j                  t        ||             y# t        $ r9}da t        j                  dj                  t        |                   Y d }~yd }~ww xY w)NFTzBUnable to remove firewall -- no further attempts will be made: {0})r]   r   r9   r<   rA   rD   rh   r   inforc   r   )rP   rl   uidr   rq   s        r   remove_firewallzDefaultOSUtil.remove_firewall   s      	 J4QWXY8vFGFtVUXYZHvVW 	$KK $fT!Wo/ 	s   A-A7 7	B9 /B44B9c                     	 | j                         }| j                  t        ||             y # t        $ r7}t	        j
                  dj                  t        |                   Y d }~y d }~ww xY w)NzNUnable to remove legacy firewall rule, won't try removing it again. Error: {0})r^   r   r9   rh   r   r   rc   r   )rP   rl   r   errors       r   remove_legacy_firewall_rulez)DefaultOSUtil.remove_legacy_firewall_rule   si    	v..0D J4QWXY 	vKK`gghlmrhstv v	vs   +. 	A.-A))A.c                 T   d}t         sd|fS 	 | j                         }	 t        j                  |||      s,| j	                  |||       t        j
                  |||       d}d|fS # t        $ rD}|j                  dk(  r+| j	                  |||       d}t        j                  |        Y d}~Ld}~wt        $ r$}t        j                  t        |              d}~ww xY w# t        $ r=}da t        j                  dj                  t        |                   d|fcY d}~S d}~ww xY w)aK  
        It checks if every iptable rule exists and add them if not present. It returns a tuple(enable firewall success status, update rules flag)
        enable firewall success status: Returns True if every firewall rule exists otherwise False
        update rules flag: Returns True if rules are updated otherwise False
        FTrz   z@please upgrade iptables to a version that supports the -C optionNzEUnable to establish firewall -- no further attempts will be made: {0})r]   r^   r   verify_iptables_rules_existr   add_iptables_rulesr   rj   r   rk   rh   r   r   rc   )rP   rl   r   is_firewall_rules_updatedr   rq   rw   r   s           r   enable_firewallzDefaultOSUtil.enable_firewall  s(    %*!  333	4..0D'CCD&RUV((d;$77fcJ04- 222   <<1$((d;\CKK$	 %
  DK(  	4$KK $fT!Wo/ 333	4sS   C! AA& "C! &	C/:B.)C! .C:CCC! !	D'*2D"D'"D'c                     	 || j                         }t        j                  t        |            }|S # t        $ r7}t        j                  dj                  t        |                   Y d }~yd }~ww xY w)Nz"Listing firewall rules failed: {0}rt   )	r^   r   r_   r'   rh   r   rk   rc   r   )rP   r   rm   rq   s       r   get_firewall_listzDefaultOSUtil.get_firewall_list-  sd    	|224**+DT+JKFM 	KK<CCDGLM	s   14 	A4-A//A4c                    t         j                  |       s| S | j                  d      }dj                  t	        j
                  |d   d      t	        j
                  |d   d      t	        j
                  |d   d      |d   |d   g      S )a  
        Azure stores the instance ID with an incorrect byte ordering for the
        first parts. For example, the ID returned by the metadata service:

            D0DF4C54-4ECB-4A4B-9954-5BDF3ED5C3B8

        will be found as:

            544CDFD0-CB4E-4B4A-9954-5BDF3ED5C3B8

        This code corrects the byte order such that it is consistent with
        that returned by the metadata service.
        -r   rz   )widthr   rZ   r[   )UUID_PATTERNre   rd   joinr	   swap_hexstring)instance_idpartss     r   _correct_instance_idz"DefaultOSUtil._correct_instance_id7  s      !!+.!!#&xx##E!HA6##E!HA6##E!HA6!H!H
  	r   c                 X   | j                         }t        j                  dj                  |             t        j                  dj                  |             |j	                         |j	                         k(  xs0 |j	                         | j                  |      j	                         k(  S )z
        Compare two instance IDs for equality, but allow that some IDs
        may have been persisted using the incorrect byte ordering.
        zcurrent instance id: {0}z former instance id: {0})get_instance_idr   verboserc   lowerr   )rP   id_thatid_thiss      r   is_current_instance_idz$DefaultOSUtil.is_current_instance_idS  s    
 &&(188AB188AB}}'--/1 M}}$";";G"D"J"J"LL	Mr   c                     | j                   S N)rI   rO   s    r   get_agent_conf_file_pathz&DefaultOSUtil.get_agent_conf_file_path^  s    (((r   c                 D   t         j                  j                  t              r(t	        j
                  t              j                         }n7t        j                  t              \  }}|dk7  st        j                  |      y| j                  |j                               S )z
        Azure records a UUID as the instance ID
        First check /sys/class/dmi/id/product_uuid.
        If that is missing, then extracts from dmidecode
        If nothing works (for old VMs), return the empty string
        r   rt   )ospathisfilePRODUCT_ID_FILEr   	read_filestripr   run_get_outputDMIDECODE_CMDr   re   r   )rP   sr~   s      r   r   zDefaultOSUtil.get_instance_ida  st     77>>/*""?399;A ,,];EBQw,,,Q/7((33r   c                 L    	 t        j                  |       S # t        $ r Y y w xY wr   )pwdgetpwnamKeyError)usernames    r   get_userentryzDefaultOSUtil.get_userentryr  s(    	<<)) 		s    	##c                    t        j                         ry| j                  |      }d}	 t        j                  dd      }|t        |j                         d         }|dk(  rd}|dk7  r	|d   |k  ryy# t        $ r
}Y d}~$d}~ww xY w)	z
        Check whether use is a system user. 
        If reset sys user is allowed in conf, return False
        Otherwise, check whether UID is less than UID_MIN
        FNUID_MINz/etc/login.defsr   ry   rz   T)r   get_allow_reset_sys_userr   r   get_line_startingwithrf   rd   IOError)rP   r   	userentryuidmin
uidmin_defrq   s         r   is_sys_userzDefaultOSUtil.is_sys_usery  s     ((*&&x0		!77	8IKJ%Z--/23 T>F1!6  		s   4A4 4	BBc                     | j                  |      }|t        j                  d|       y|dd|d|g}ndd|g}||j                  d|g       | j	                  |dj                  |             y)	z5
        Create user account with 'username'
        Nz%User {0} already exists, skip useradduseraddr/   z-ez-cz!Failed to create user account:{0}err_msg)r   r   r   extend _run_command_raising_OSUtilErrorrc   )rP   r   
expirationcommentr   cmds         r   r   zDefaultOSUtil.useradd  s     &&x0	 KK?J!dHdJ?CdH-CJJg'--c;^;e;efn;o-pr   c                     | j                  |      rt        dj                  |            t        j                  |||      }| j                  dd||gdj                  |             y )Nz1User {0} is a system user, will not set password.usermodr-   zFailed to set password for {0}r   )r   r
   rc   r	   gen_password_hashr   )rP   r   passwordcrypt_idsalt_lenpasswd_hashs         r   chpasswdzDefaultOSUtil.chpasswd  sp    H%  89?9IK K008XN--y$X.V6V6]6]^f6g 	. 	ir   c                     t               S r   r   rO   s    r   	get_userszDefaultOSUtil.get_users  s
    zr   c                    t        j                         }t        j                  j	                  |d      }|s$t        j                  j                  |      skt        j                  |       t        j                  j	                  |t        j                  d      }dj                  |      }t        j                  ||       d }|rdj                  |      }ndj                  |      }t        j                  j                  |      rt        j                  ||      du r%t        j                  |dj                  |             t        j                  |d       y t        j                  j                  |      ra	 t        j                  |      }	|	j                  d	      }
|
D cg c]	  }||vs| }
}t        j                   |d	j	                  |
             y y c c}w # t"        $ r}t%        d
j                  |            d }~ww xY w)NrS   sudoersz
#includedir {0}
z{0} ALL=(ALL) NOPASSWD: ALLz{0} ALL=(ALL) ALLFz{0}
i   rY   zFailed to remove sudoer: {0})r   get_sudoers_dirr   r   r   isdirr   mkdirpardirrc   append_filer   findstr_in_filechmodr   rd   
write_filer   r
   )rP   r   nopasswdremovesudoers_dirsudoers_wagentsudoers_fileinclude_sudoers_dirsudoercontentr   xrq   s                r   conf_sudoerzDefaultOSUtil.conf_sudoer  s   **,k9=77==-{+!ww||KIN&;&B&B;&O#$$\3FGF6==hG,33H=77>>.1,,^VDM$$^W^^F5KLNN>51 ww~~n-P&00@G%mmD1G*1GQXQ5FqGGG''		'8JK . H P%&D&K&KA&NOOPs0   <*G" &	G0G4'G" G" "	H
+HH
c                    	 t        j                         }t        j                  |      }|j	                  d      }|D cg c]  }|j                  d      r| }}|j                  dd       t        j                  |dj                  |             y c c}w # t        $ r}t        dj                  |            d }~ww xY w)NrY   zroot:r   zroot:*LOCK*:14600::::::z"Failed to delete root password:{0})r   get_passwd_file_pathr   r   rd   
startswithr   r   r   r   r
   rc   )rP   passwd_file_pathpasswd_contentpasswdr   
new_passwdrq   s          r   del_root_passwordzDefaultOSUtil.del_root_password  s    	N#88:%//0@AN#))$/F%+I1<<3H!IJIa!:; 0$))J2GH J  	NBII!LMM	Ns/   >B  BB9B B 	C#B==Cc                     t        j                         }t        j                  j	                  | j                  d|            }|S )Nz$HOME)r   get_home_dirr   r   normpathreplace)filepathhomer   s      r   
_norm_pathzDefaultOSUtil._norm_path  s6      "ww 0 0$ ?@r   c                    |\  }}| j                  |      }t        j                  j                  |      }t	        j
                  |d|       t        j                         }t        j                  j                  ||dz         }t        j                  j                  |      st        dj                  |            t        j                  ||       |dz   }t        t        j                               }	|	j!                  |      }
t	        j"                  ||
       | j%                  |d       | j%                  |d       t        j&                  |d       t        j&                  |d       y	)
z.
        Deploy id_rsa and id_rsa.pub
          moder>   z.prvzCan't find {0}.prv.pub#unconfined_u:object_r:ssh_home_t:s0    N)r   r   r   dirnamer   r   r   get_lib_dirr   r   r
   rc   shutilcopyfiler   get_openssl_cmdget_pubkey_from_prvr   set_selinux_contextr   )rP   r   keypairr   
thumbprintdir_pathlib_dirprv_pathpub_path	crytputilpubs              r   deploy_ssh_keypairz DefaultOSUtil.deploy_ssh_keypair  s    #jt$77??4(xe8<""$77<<f)<=ww~~h'299*EFF$'&=d2245	++H5Hc*  +PQ  'LM
u
5!r   c                 b    t        t        j                               }|j                  ||       y r   )r   r   r   
crt_to_ssh)rP   
input_fileoutput_file	cryptutils       r   openssl_to_opensshz DefaultOSUtil.openssl_to_openssh  s%    d2245	Z5r   c                 *   |\  }}}|t        d      t        t        j                               }| j	                  |      }t
        j                  j                  |      }t        j                  |d|       |Y|j                  d      st        dj                  |            |j                  d      s|dz  }t        j                  ||       n|t        j                         }t
        j                  j                  ||dz         }	t
        j                  j!                  |	      st        d	j                  |            t
        j                  j                  ||d
z         }
|j#                  |	      }t        j                  |
|       | j%                  |
d       | j'                  |
|       t        j(                  |
d       nt        d      | j%                  |d       t        j*                  ||       t        j(                  |d       y)z'
        Deploy authorized_key
        NzPublic key path is Noner   r   zssh-zBad public key: {0}rY   z.crtzCan't find {0}.crtr   r   r   z-SSH public key Fingerprint and Value are Noner   )r
   r   r   r   r   r   r   r   r   r   r   rc   endswithr   r   r   r   get_pubkey_from_crtr   r  r   chowner)rP   r   pubkeyr   r   valuer  r  r  crt_pathr  r  s               r   deploy_ssh_pubkeyzDefaultOSUtil.deploy_ssh_pubkey  s    #)j%<788d2245	t$77??4(xe8<##F+!"7">">u"EFF>>$'e,#&&(Gww||GZ&-@AH77>>(+!"6"="=j"IJJww||GZ&-@AH//9C#.$$X%JL##Hd3NN8U+MNN  'LMx(tU#r   c                     | j                   dk(  r4t        j                  dd      dk(  rd| _         | j                   S d| _         | j                   S )zX
        Checks and sets self.selinux = True if SELinux is available on system.
        Nzwhich getenforceFchk_errr   T)rJ   r   runrO   s    r   is_selinux_systemzDefaultOSUtil.is_selinux_system$  sJ     <<4}}/?1D# ||  %||r   c                 v    | j                         r)t        j                  d      d   }|j                  d      S y)zS
        Calls shell command 'getenforce' and returns True if 'Enforcing'.
        
getenforcer   	EnforcingF)r  r   r   r   )rP   rm   s     r   is_selinux_enforcingz"DefaultOSUtil.is_selinux_enforcing/  s9     !!#--l;A>F$$[11r   c                 <   | j                         r`t        j                  j                  |      s%t	        j
                  dj                  |             y	 t        j                  d||gd       yy# t        j                  $ r}|j                  cY d}~S d}~ww xY w)za
        Calls shell 'chcon' with 'path' and 'con' context.
        Returns exit result.
        zPath does not exist: {0}r   chconT	log_errorNr   )r  r   r   existsr   r   rc   r   r_   r   rj   )rP   r   concmd_errs       r   r   z!DefaultOSUtil.set_selinux_context9  s    
 !!#77>>$'7>>tDE*%%wT&:dK  $ )) *)))*s   A2 2BBBBc                    |rdnd}t        j                         }t        j                  |      j	                  d      }t        j                  |d|       t        j                  |d|       t        j                  |dt        t        j                                      t        j                  |dj                  |             t        j                  dj                  |rdnd	             t        j                  d
       y )NnoyesrY   PasswordAuthenticationChallengeResponseAuthenticationClientAliveIntervalz.{0} SSH password-based authentication methods.DisabledEnabledz8Configured SSH client probing to keep connections alive.)r   get_sshd_conf_file_pathr   r   rd   r	   set_ssh_configr?   get_ssh_client_alive_intervalr   r   r   r   rc   )rP   disable_passwordoptionconf_file_path	conf_files        r   	conf_sshdzDefaultOSUtil.conf_sshdI  s    )u557&&~6<<TB		+CVL	+LfU	+@#dFhFhFjBklNDIIi,@ADV*:J	J	LNOr   c                 0   d}t        j                  |      }|D cg c]  }t        j                  ||       c}D ]&  }|dj	                  |j                  d            c S  dj	                  ||      }t        dj	                  |      |      c c}w )Nz,(sr[0-9]|hd[c-z]|cdrom[0-9]|cd[0-9]|vd[b-z])z/dev/{0}r   zJThe following devices were found, but none matched the pattern [{0}]: {1}
z!Failed to get dvd device from {0})rw   inner)r   listdirr`   re   rc   rg   r
   )rP   dev_dirrn   device_listdevdvdinner_details          r   get_dvd_devicezDefaultOSUtil.get_dvd_deviceU  s    Ajj)6ABsBHHWc*B 	7C!((166	7228&+2N 	AHHQ ,. 	. Cs   Bc                 `   || j                         }|t        j                         }t        j                  d      d   }| j                  ||      }|t        j                  d||       y t        j                  j                  |      st        j                  |       d}t        d|      D ]n  }	| j                  ||g dd      \  }
}|
dk(  rt        j                  d	        y t        j                  d
|	|dz
  |       |	|k  sZt        j                   |       p |rt#        d|      y )Nmountr   z{0} is already mounted at {1}rt   )-oror!   zudf,iso9660,vfatF)r2  r  r   zSuccessfully mounted dvdz5Mounting dvd failed [retry {0}/{1}, sleeping {2} sec]zFailed to mount dvd device)r7  )r>  r   get_dvd_mount_pointr   r   get_mount_pointr   r   r   r   r   makedirsr{   r@  rk   timesleepr
   )rP   	max_retryr  
dvd_devicemount_point
sleep_time
mount_listexistingerrretryreturn_codes              r   	mount_dvdzDefaultOSUtil.mount_dvd`  s+    ,,.J224K--g6q9
''
J?KK7XNww}}[)KK$1i( 	+E#zz**51W27  *  9K a67KM	 
 9$JJz*	+  :#FF r   c                     |t        j                         }| j                  ||      }|r |dk7  rt        dj	                  |            y y )Nr  r   z#Failed to unmount dvd device at {0})r   rC  umountr
   rc   )rP   r  rJ  rP  s       r   
umount_dvdzDefaultOSUtil.umount_dvd  sP    224Kkk+wk?{a'CJJ;WXX (7r   c                 l   | j                         }|j                  dd      d   }d}t        j                  ||      ry 	 t	        j
                  d|g       y # t        j                  $ rH}|r<dj                  |j                  |j                  |j                        }t        |      Y d }~y d }~ww xY w)N/r   z	(vd[b-z])ejectz7Failed to eject dvd: ret={0}
[stdout]
{1}

[stderr]
{2})r>  rsplitr`   searchr   r_   r   rc   rj   stdoutstderrr
   )rP   r  r<  r;  rn   r%  rw   s          r   	eject_dvdzDefaultOSUtil.eject_dvd  s    !!#jja #99Wc"	'!!7C.1%% 	'TVG..O  "#&& 	's    A B3+>B..B3c                     	 | j                          y # t        $ r.}t        j                  dj	                  |             Y d }~y d }~ww xY w)Nz Could not load ATAPI driver: {0})load_atapiix_modrh   r   rk   rc   )rP   rq   s     r   try_load_atapiix_modz"DefaultOSUtil.try_load_atapiix_mod  sA    	F!!# 	FKK:AA!DEE	Fs    	A
$AA
c                    | j                         ry t        j                  d      \  }}|dk7  rt        d      t        j
                  j                  d|j                  d      d      }t        j
                  j                  |      st        dj                  |            t        j                  d|z         \  }}|dk7  rt        d	      | j                  d
      st        d      y )Nzuname -rr   zFailed to call uname -rz/lib/modulesrY   zkernel/drivers/ata/ata_piix.kozCan't find module file:{0}zinsmod z,Error calling insmod for ATAPI CD-ROM driverrZ   )rH  z"Failed to load ATAPI CD-ROM driver)
is_atapiix_mod_loadedr   r   rh   r   r   r   r   r   rc   )rP   retkern_versionmod_pathrm   s        r   r^  zDefaultOSUtil.load_atapiix_mod  s    %%'%44Z@\!856677<< , 2 24 8 @B ww~~h'8??IJJ..y8/CDV!8JKK))A)6@AA 7r   c                     t        d|      D ]S  }t        j                  dd      }|dk(  rt        j                  d        y||dz
  k  s?t        j                  d       U y)Nr   zlsmod | grep ata_piixFr  z2Module driver for ATAPI CD-ROM is already present.Tr   )r{   r   r  r   r   rF  rG  )rP   rH  rO  rb  s       r   ra  z#DefaultOSUtil.is_atapiix_mod_loaded  s\    1i( 	E-- 7GCaxPQy1}$

1	 r   c                 4   |sg }dg}|j                  |||gz          	 t        j                  ||      }d|fS # t        j                  $ rJ}dj	                  ||j
                  |j                  |j                        }|j
                  |fcY d }~S d }~ww xY w)Nr@  r!  z-[{0}] returned {1}:
 stdout: {2}

stderr: {3}r   )r   r   r_   r   rc   rj   rZ  r[  )	rP   devicerJ  r2  r  r   rm   r%  details	            r   r@  zDefaultOSUtil.mount  s    Fi

6V[112	.**3'BF &y %% 	.GNNsT[TfTf0F%%v--	.s   : B?BBBc                     	 t        j                  d|g|       y# t         j                  $ r}|j                  cY d }~S d }~ww xY w)NrS  r!  r   )r   r_   r   rj   )rP   rJ  r  r%  s       r   rS  zDefaultOSUtil.umount  sE    	&!!8["9WM  %% 	&%%%	&s    AA A Ac                 `    t        j                  dd       t        j                  dd       y )Nz-iptables -D INPUT -p udp --dport 68 -j ACCEPTFr  z-iptables -I INPUT -p udp --dport 68 -j ACCEPT)r   r  rO   s    r   allow_dhcp_broadcastz"DefaultOSUtil.allow_dhcp_broadcast  s(     	E#	%E#	%r   c                    |t         }t        j                         }|D ]  }t        j                  |      }t
        j                  j                  ||      }t
        j                  j                  |      rt        j                  |       t
        j                  j                  |      st        j                  d||       t        j                  ||        y NzMove rules file {0} to {1})__RULES_FILES__r   r   r   	base_namer   r   r   r   r   r   rk   r   move)rP   rules_filesr  src	file_namedests         r   remove_rules_filesz DefaultOSUtil.remove_rules_files  s    )K""$ 	'C **3/I77<<3Dww~~d#		$ww~~c"8)TJC&	'r   c                    |t         }t        j                         }|D ]  }t        j                  |      }t
        j                  j                  ||      }t
        j                  j                  |      rXt
        j                  j                  |      sxt        j                  d||       t        j                  ||        y rm  )rn  r   r   r   ro  r   r   r   r   r   rk   r   rp  )rP   rq  r  rt  filenamerr  s         r   restore_rules_filesz!DefaultOSUtil.restore_rules_files  s    )K""$ 	'D))$/H'',,w1Cww~~d#ww~~c"8(DIC&	'r   c                 n    | j                         }| j                  |      }t        j                  |      S )zg
        Convenience function, returns mac addr bound to
        first non-loopback interface.
        )get_if_name
get_if_macr	   hexstr_to_bytearray)rP   ifnameaddrs      r   get_mac_addrzDefaultOSUtil.get_mac_addr  s1    
 !!#v&++D11r   c           	         t        j                   t         j                  t         j                  t         j                        }t	        j
                  d|dd dz   j                  d            }t        j                  |j                         t        |      }|j                          dj                  |dd D cg c]  }d	t        j                  |      z   c}      S c c}w )
z=
        Return the mac-address bound to the socket.
        256sN   z                                                                                                                                                                                                                                                 latin-1rt         z%02X)socketAF_INET
SOCK_DGRAMIPPROTO_UDPstructpackencodefcntlioctlfilenoIOCTL_SIOCGIFHWADDRcloser   r	   
str_to_ord)rP   r}  sockparamr   chars         r   r{  zDefaultOSUtil.get_if_mac  s     }}V^^#..#//1 FVCR[J%?$G$G	$RS{{4;;=*=uE

wwtBr{St!4!4T!::STTSs   8Cc                  J    t        j                         d   } | dk(  rd}|S d}|S )z
        Return the sizeof struct ifinfo. On 64-bit platforms the size is 40 bytes;
        on 32-bit platforms the size is 32 bytes.
        r   32bit    (   )platformarchitecture)
python_arcstruct_sizes     r   _get_struct_ifconf_sizez%DefaultOSUtil._get_struct_ifconf_size  s6     **,Q/
&'1b 8:r   c                 "   d}t         j                         }||z  }t        j                  dd|z        }t        j                  d||j                         d         }t        j                  t        j                  t        j                  t        j                        }t        j                  |j                         t        |      }t        j                  d|      d   }|j                          ||k(  rt!        j"                  d|       t%        |      }	i }
t'        d||      D ]g  }|	||t(        z    j+                  dd      d   }t-        |      dkD  s1|j/                  d      }||
vsGt        j0                  |	|d	z   |d
z          |
|<   i |
S )z
        Return a dictionary mapping from interface name to IPv4 address.
        Interfaces without a name are ignored.
        rE   B    iLr   z9SIOCGIFCONF returned more than {0} up network interfaces.r   r     r  )rG   r  arrayr  r  buffer_infor  r  r  r  r  r  r  IOCTL_SIOCGIFCONFunpackr  r   rk   r   r{   IFNAMSIZrd   lendecode	inet_ntoa)rP   expectedr  
array_sizebuffr  r  rb  retsizeifconf_buffifacesr}   iface
iface_names                 r   _get_all_interfacesz!DefaultOSUtil._get_all_interfaces  se   
 #;;=+
{{3
 23D*d.>.>.@.CD}}V^^V->->@R@RSkk$++-):EB==s+A.

j KK /19; %T*q*k2 	VA!h,/55eQ?BE5zA~"\\)4
V+)/)9)9+a"fQQSV:T)UF:&	V r   c                     | j                         }| j                         }||v r|||   fS |j                         D ]@  }| j                  |      rt	        j
                  dj                  |             |||   fc S  y)z
        Return the interface name, and IPv4 addr of the "primary" interface or,
        failing that, any active non-loopback interface.
        zChoosing non-primary [{0}])rt   rt   )get_primary_interfacer  keysis_loopbackr   r   rc   )rP   primaryr  r  s       r   get_first_ifzDefaultOSUtil.get_first_if;  s    
 ,,.))+fF7O++ ++- 	6J##J/8??
KL!6*#555	6
 r   c           
         d}i }| d   }t        d |j                  d            D ]  }|||j                         <   |dz  } 	 |d   }|d   }|d   }|d   }|d	   }	|d
   }
g }| dd D ]U  }|j                  d      }t        |      dkD  s#t        ||   ||   ||   ||
   ||   ||	         }|j                  |       W |S # t        $ r+ dj	                  |      }t        j                  |       g cY S w xY w)z
        Construct a list of network route entries
        :param list(str) proc_net_route: Route table lines, including headers, containing at least one route
        :return: List of network route objects
        :rtype: list(RouteEntry)
        r   c                     t        |       dkD  S )Nr   )r  )hs    r   <lambda>z1DefaultOSUtil._build_route_list.<locals>.<lambda>X  s    s1vz r   	r   IfaceDestinationGatewayFlagsMetricMaskz=/proc/net/route is missing key information; headers are [{0}]N)
filterrd   r   r   rc   r   r   r  r   append)proc_net_routeidxcolumn_indexheader_lineheader	idx_ifaceidx_destidx_gw	idx_flags
idx_metricidx_maskrw   
route_listentryroute	route_objs                   r   _build_route_listzDefaultOSUtil._build_route_listM  sJ    $Q'1;3D3DT3JK 	F+.L(1HC	
	$W-I#M2H!),F$W-I%h/J#F+H 
#AB' 	-EKK%E5zA~&uY'7x%PV-Y^_gYh',Y'7z9JL	!!),	-   	QXXYdeCLLI	s   C 1C76C7c                     	 t        d      5 } t        t        t        j                  | j                                     cddd       S # 1 sw Y   g S xY w# t        $ r*}t        j                  dt        |             Y d}~g S d}~ww xY w)a	  
        Return a list of strings comprising the route table, including column headers. Each line is stripped of leading
        or trailing whitespace but is otherwise unmolested.

        :return: Entries in the text route table
        :rtype: list(str)
        /proc/net/routeNzCannot read route table [{0}])
openlistmapr?   r   	readlinesrh   r   r   r   )routing_tablerq   s     r   read_route_tablezDefaultOSUtil.read_route_tablep  s}    	C'( GMC		=+B+B+DEFG G G
 	  	CLL8$q'BB		Cs3   A 1A	A AA A 	BBBc                     g }t        |       }|dk  rt        j                  d       |S |dk(  rt        j                  d       |S t        j	                  |       }|S )z
        Construct a list of all network routes known to this system.

        :param list(str) route_table: List of text entries from route table, including headers
        :return: a list of network routes
        :rtype: list(RouteEntry)
        r   z"/proc/net/route is missing headersz"/proc/net/route contains no routes)r  r   r   rG   r  )route_tabler  counts      r   get_list_of_routesz DefaultOSUtil.get_list_of_routes  se     
K 19LL=>
 	 aZLL=>  '88EJr   c                   	
 d
d	d}| j                   st        j                  d       t        j	                         }	
fd}t        t        |t        j                  |                  }t        |      dkD  rd }t        ||      }|j                  }|d	}| j                   s{t        d
      5 }|j                         }t        j                  d       t        j                  dj                  |             t        j                  d       d| _         ddd       |S |S t        j                  dj                  |             d| _         |S # 1 sw Y   |S xY w)a  
        Get the name of the primary interface, which is the one with the
        default route attached to it; if there are multiple default routes,
        the primary has the lowest Metric.
        :return: the interface which has the default route
        rz   00000000Nz-Examine /proc/net/route for primary interfacec                 \    | j                   k(  xr t        | j                        z  k(  S r   )r8   rf   flags)r  DEFAULT_DESTRTF_GATEWAYs    r   
is_defaultz7DefaultOSUtil.get_primary_interface.<locals>.is_default  s-    $$4fU[[9IK9W[f9ffr   r   c                 ,    t        | j                        S r   )rf   metric)r  s    r   
get_metricz7DefaultOSUtil.get_primary_interface.<locals>.get_metric  s    5<<((r   )keyrt   r  zOCould not determine primary interface, please ensure /proc/net/route is correctz Contents of /proc/net/route:
{0}z1Primary interface examination will retry silentlyTzPrimary interface is [{0}]F)rK   r   r   rG   r  r  r  r  r  min	interfacer  readrk   rc   )rP   primary_interfacer  r  
candidatesr  primary_routerouting_table_fhrouting_table_textr  r  s            @@r   r  z#DefaultOSUtil.get_primary_interface  sH    ! ))KKGH#446	g &]-M-Mk-Z[\
z?Q)  

;M - 7 7$ "--+, 60@)9)>)>)@&KK !K LKK C J JK] ^_KK ST15D.6 !    KK4;;<MNO).D&  6 ! s   1A&EEc                 (    | j                         |k(  S )z
        Indicate whether the specified interface is the primary.
        :param ifname: the name of the interface - eth0, lo, etc.
        :return: True if this interface binds the default route
        )r  )rP   r}  s     r   is_primary_interfacez"DefaultOSUtil.is_primary_interface  s     ))+v55r   c                    t        j                   t         j                  t         j                  t         j                        }|dz   }t	        j
                  |j                         t        |      }t        j                  d|dd       \  }|dz  dk(  }| j                  s&t        j                  dj                  |||             |j                          |S )z=
        Determine if a named interface is loopback.
        a                                                                                                                                                                                                                                                                   HrE   r     z2interface [{0}] has flags [{1}], is loopback [{2}])r  r  r  r  r  r  r  IOCTL_SIOCGIFFLAGSr  r  rK   r   r   rc   r  )rP   r}  r   ifname_buffresultr  
isloopbacks          r   r  zDefaultOSUtil.is_loopback  s     MM&..&*;*;V=O=OP
+QXXZ);[IsF2bM2QY!^
))KK ,,2F65*,MO		r   c                      y)z
        OS specific, this should return the decoded endpoint of
        the wireserver from option 245 in the dhcp leases file
        if it exists on disk.
        :return: The endpoint if available, or None
        Nr   rO   s    r   get_dhcp_lease_endpointz%DefaultOSUtil.get_dhcp_lease_endpoint  s     r   c                    d}d}d}d}d}d}t        j                  d      }t        j                  dj	                  |              t        j
                  |       D ]  }t        |      j                         }	||	v s"d}
d}d	}|	j                         D ]r  }|j                  |      rd}
d	}||v rpd
|v rd}%	 |j                  dd      d   j                  d      }t        j                  j                  ||      }|t        j                  j                         kD  rd}||v rUt        j                  dj	                  |
|du|             |r|
|
}t        j                  dj	                  |             |j!                  |      }|dj	                  t#        |j%                  d      d      t#        |j%                  d      d      t#        |j%                  d      d      t#        |j%                  d      d            }
u  |&t        j                  dj	                  |             |S t        j                  d       |S #  t        j                  dj	                  |             Y xY w)z
        Try to discover and decode the wireserver endpoint in the
        specified dhcp leases path.
        :param pathglob: The path containing dhcp lease files
        :return: The endpoint if available, otherwise None
        Nleasezoption unknown-245expire}z%Y/%m/%d %H:%M:%SzV\s*option\s+unknown-245\s+([0-9a-fA-F]+):([0-9a-fA-F]+):([0-9a-fA-F]+):([0-9a-fA-F]+);z looking for leases in path [{0}]TneverF r[   r\   ;z"could not parse expiry token '{0}'z$dhcp entry:{0}, 245:{1}, expired:{2}zfound endpoint [{0}]z{0}.{1}.{2}.{3}r   rE   rz   rZ   zcached endpoint found [{0}]zcached endpoint not found)r`   ra   r   r   rc   globr  r  
splitlinesr   rd   r   datetimestrptimeutcnowr   re   rf   rg   )pathglobendpointHEADER_LEASEHEADER_OPTION_245HEADER_EXPIREFOOTER_LEASEFORMAT_DATETIMEoption_245_re
lease_fileleasescached_endpointoption_245_matchexpiredro   expire_stringexpire_dates                   r   get_endpoint_from_leases_pathz+DefaultOSUtil.get_endpoint_from_leases_path  sk    0 -

eg 	6==hGH))H- $	DJ*%**,F F*"&#' "--/ DD|4*."&&$."d?&+G`04

30B20F0L0LS0Q.6.?.?.H.HXg.h#.1B1B1I1I1K#K.3G &-$J$Q$Q+-=T-I7%T U&?+F'6H"KK(>(E(Eh(OP ,9+>+>t+D(+7.?.F.F #$4$:$:1$=r B #$4$:$:1$=r B #$4$:$:1$=r B #$4$:$:1$=r B	/DO5D$	DJ KK5<<XFG  KK34-` &-Q-X-XY]-^ _s   9A'I&I4c                 *   	 g d}t        j                  |      }|j                  d      D ]&  }|j                  d      s|j                  d      s& y y# t        $ r3}t        j                  dt              t        |             Y d }~yd }~ww xY w)N)ipr  showrY   z0.0.0.0 zdefault FTz-Cannot get the routing table. {0} failed: {1})r   r_   rd   r   r   r   rk   r   )rP   	route_cmdroutesr  rq   s        r   is_missing_default_routez&DefaultOSUtil.is_missing_default_route   s    		/I**95Fd+ !##J/53C3CJ3O !  	KKGiZ^_`Zab	s$   AA A A 	B)BBc                     d}d}|s;| j                         d   }t        |      dk\  }|st        j                  d       |s;|S )Nrt   Fr   rz   )r  r  rF  rG  )rP   if_nameif_founds      r   rz  zDefaultOSUtil.get_if_name,  sJ    '')!,G7|q(H

1	 
 r   c                 (    | j                         d   S )Nr   )r  rO   s    r   get_ip4_addrzDefaultOSUtil.get_ip4_addr6  s      "1%%r   c                 \    	 ddddd|g}t        j                  |      S # t        $ r Y yw xY w)Nr  r  add255.255.255.255r;  rt   r   r_   r   rP   r}  r!  s      r   set_route_for_dhcp_broadcastz*DefaultOSUtil.set_route_for_dhcp_broadcast9  s=    	w/@%PI((33 		    	++c                 ^    	 ddddd|g}t        j                  |       y # t        $ r Y y w xY w)Nr  r  delr+  r;  r,  r-  s      r   remove_route_for_dhcp_broadcastz-DefaultOSUtil.remove_route_for_dhcp_broadcast@  s:    	w/@%PI!!), 		s     	,,c                      yNTr   rO   s    r   is_dhcp_availablezDefaultOSUtil.is_dhcp_availableG  s    r   c                      y)NFr   rO   s    r   is_dhcp_enabledzDefaultOSUtil.is_dhcp_enabledJ  s    r   c                      y r   r   rO   s    r   stop_dhcp_servicezDefaultOSUtil.stop_dhcp_serviceM      r   c                      y r   r   rO   s    r   start_dhcp_servicez DefaultOSUtil.start_dhcp_serviceP  r:  r   c                      y r   r   rO   s    r   start_networkzDefaultOSUtil.start_networkS  r:  r   c                      y r   r   rO   s    r   start_agent_servicez!DefaultOSUtil.start_agent_serviceV  r:  r   c                      y r   r   rO   s    r   stop_agent_servicez DefaultOSUtil.stop_agent_serviceY  r:  r   c                      y r   r   rO   s    r   register_agent_servicez$DefaultOSUtil.register_agent_service\  r:  r   c                      y r   r   rO   s    r   unregister_agent_servicez&DefaultOSUtil.unregister_agent_service_  r:  r   c                      y r   r   rO   s    r   restart_ssh_servicez!DefaultOSUtil.restart_ssh_serviceb  r:  r   c                 \    	 ddd|d|g}t        j                  |      S # t        $ r Y yw xY w)z&
        Add specified route 
        r  r  r*  viart   r,  )rP   netmaskgatewayr   s        r   	route_addzDefaultOSUtil.route_adde  s<    	%eW=C((-- 		r/  c                 Z    | j                         D cg c]  }t        |       c}S c c}w r   )rd   rf   )textns     r   _text_to_pid_listzDefaultOSUtil._text_to_pid_listo  s      $

-1A---s   (c                     	 t        j                  |       }| ||      }t        j                  |      S # t        $ r}g cY d }~S d }~ww xY wr   )r   r_   rG   rR  r   )r   transform_command_outputrm   	exceptions       r   _get_dhcp_pidzDefaultOSUtil._get_dhcp_pids  sM    	**73F'31&9 226:: 	I	s   36 	AA AAc                 (    | j                  ddg      S )Npidofdhclient)rV  rO   s    r   get_dhcp_pidzDefaultOSUtil.get_dhcp_pid}  s    !!7J"788r   c                 Z    t        j                  d|       | j                  d|gd       y )Nz/etc/hostnamehostnameFr!  )r   r   _run_command_without_raisingrP   r\  s     r   set_hostnamezDefaultOSUtil.set_hostname  s*    OX6)):x*@E)Rr   c                     d}g d}|D ]`  }t         j                  j                  |      s#t        j                  ||      r y t        j
                  |ddj                  |             b y )Nz7^[^#]*?send\s*host-name.*?(<hostname>|gethostname[(,)]))z/etc/dhcp/dhclient.confz/etc/dhcp3/dhclient.confz/etc/dhclient.confzsend host-namezsend host-name "{0}";)r   r   r   r   findre_in_fileupdate_conf_filerc   )rP   r\  autosenddhclient_filesr4  s        r   set_dhcp_hostnamezDefaultOSUtil.set_dhcp_hostname  se    Mf' 	PI77>>),&&y(;%%i&6&=&D&DX&NP	Pr   c                    |dz   }t        d|      D ]  }t        j                  dj                  |      ||k  rdgng       }|dk(  r y t	        j
                  dj                  ||             ||k  r:t	        j                  dj                  |             t        j                  |       t	        j
                  d        y )Nr   zifdown {0} && ifup {0})expected_errorsr   z&failed to restart {0}: return code {1}zretrying in {0} secondszexceeded restart retries)	r{   r   r  rc   r   rk   r   rF  rG  )rP   r}  retriesr   retry_limitattemptrP  s          r   
restart_ifzDefaultOSUtil.restart_if  s    kQ, 		8G#--(@(G(G(Ohoryhybcad  @B  CKaKK@GGP[\]$5<<TBC

4 67		8r   c                     | j                  |       | j                  |       | j                         }| j                  |       y r   )re  set_hostname_recordrz  rk  )rP   r\  r}  s      r   publish_hostnamezDefaultOSUtil.publish_hostname  s8    x(  *!!#r   c                     t        j                  d      D ]&  }|j                  d      s| j                  ||       ( y )Nz
/sys/blocksd)r   r8  r   set_block_device_timeout)rP   timeoutr;  s      r   set_scsi_disks_timeoutz$DefaultOSUtil.set_scsi_disks_timeout  s6    ::l+ 	<C~~d#--c7;	<r   c                    |~|{dj                  |      }t        j                  |      }|j                         d   j	                         }||k7  r.t        j
                  ||       t        j                  d||       y y y y )Nz/sys/block/{0}/device/timeoutr   z,Set block dev timeout: {0} with timeout: {1})rc   r   r   r
  rstripr   r   r   )rP   r;  rr  	file_pathr   originals         r   rq  z&DefaultOSUtil.set_block_device_timeout  s    ?w27>>sCI((3G))+A.557H7"##Iw7J* #	  3?r   c                     |rW|rU|j                  d      D ]A  }t        j                  ||      s|j                         }t        |      dkD  r|d   c S dc S  y)a  
        Example of mountlist:
            /dev/sda1 on / type ext4 (rw)
            proc on /proc type proc (rw)
            sysfs on /sys type sysfs (rw)
            devpts on /dev/pts type devpts (rw,gid=5,mode=620)
            tmpfs on /dev/shm type tmpfs
            (rw,rootcontext="system_u:object_r:tmpfs_t:s0")
            none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
            /dev/sdb1 on /mnt/resource type ext4 (rw)
        rY   rz   N)rd   r`   rY  r  )rP   	mountlistrg  r  tokenss        r   rD  zDefaultOSUtil.get_mount_point  sZ     &". BIIfe,"[[]F(+Fa6!9ATA	B
 r   c               #   .  K   t         j                  j                  t              rnt        j                  t              D ]Q  } t        j                  t         j                  j                  t        | d            }|j                  d      }| |f S yyw)z
        Enumerate all storage device IDs.

        Args:
            None

        Returns:
            Iterator[Tuple[str, str]]: VmBus and storage devices.
        	device_idz{}
N)	r   r   r#  STORAGE_DEVICE_PATHr8  r   r   r   r   )vmbusdeviceidguids      r   _enumerate_device_idz"DefaultOSUtil._enumerate_device_id  ss      77>>-.$78 "#--bggll;NPUWb.cd~~f-Tk!" /s   BBc           	         d}t        j                  dj                  | |             	 t        j	                         D ]  \  }}|j                  |       s||k(  st        j                  t        |z         D ]  \  }}}|j                  d      }|d   dk(  r*||k7  s|d   j                  d      d   dk(  r|d	   }|c c S |D ]:  }	d|	v sd|	j                  d      d	   k(  s |	j                  d      d
   }|c c c S    	 y# t        t        f$ r+}
t        j                  d| |t        |
             Y d}
~
yd}
~
ww xY w)a  
        Search the filesystem for a device by ID or prefix.

        Args:
            gen1_device_prefix (str): Gen1 resource disk prefix.
            gen2_device_id (str): Gen2 resource device ID.

        Returns:
            str: The found device.
        Nz%Searching gen1 prefix {0} or gen2 {1}rV  r\   block:1r   r   z(Error getting device for {0} or {1}: {2})r   r   rc   rG   r  r   r   walkr}  rd   OSErrorr   rk   r   )gen1_device_prefixgen2_device_idrg  r~  r  rootdirsfilesroot_path_partsdexcs              r   search_for_resource_diskz&DefaultOSUtil.search_for_resource_disk  sP    ;BBCUWefg	s,AAC 2t??#56$.:P-/WW5H55P-Q 2)dE*.**S/ +2.'9 $ 6 / 3 9 9# >r Bc I%)!WF#)M &* 2#&!81773<?0J-.WWS\!_F+1M2!220  ! 	sKKBDVXfhlmphqrr	ss6   0D A%D  	D 
D "D >D D?!D::D?c                     |dkD  ryd}|dkD  rd}|dz
  }dj                  ||      }t        j                  |t              }t	        j
                  d	j                  |             |S )
z>
        Return device name attached to ide port 'n'.
        rZ   Nr  r   00000001rz   z
{0}-000{1})r  r  zFound device: {0})rc   rG   r  GEN2_DEVICE_IDr   r   )rP   port_idg0r  rg  s        r   device_for_ide_portz!DefaultOSUtil.device_for_ide_port  su     Q;Q;BkG)00W=771) 8 
 	'..v67r   c                 V    t        j                  t        j                         |       y )N)contents)r   r   r   get_published_hostnamer^  s     r   rm  z!DefaultOSUtil.set_hostname_record  s    D779HMr   c                 \   t        j                         }t        j                  j	                  |      sc| j                         }|)t        j                  d       t        j                         }t        j                  d||       | j                  |       t        j                  |      }|S )Nz.Retrieving hostname using socket.gethostname()zLPublished hostname record does not exist, creating [{0}] with hostname [{1}])r   r  r   r   r#  _get_cloud_init_hostnamer   r   r  gethostnamerm  r   r   )rP   hostname_recordr\  records       r   get_hostname_recordz!DefaultOSUtil.get_hostname_record  s    557ww~~o. 446HLM!--/KKfhw  zB  C$$X.##O4r   c                  \   d} 	 t         j                  j                  |       rIt        j                  d|        t        | d      5 }t        j                  |      }ddd       dv r|d   S y# 1 sw Y   xY w# t        $ r)}t        j                  dt        |             Y d}~yd}~ww xY w)z
        Retrieves the hostname set by cloud-init; returns None if cloud-init did not set the hostname or if there is an
        error retrieving it.
        z /var/lib/cloud/data/set-hostnamezRetrieving hostname from {0}rNr\  zError retrieving hostname: {0})r   r   r#  r   r   r  jsonloadrh   rk   r   )hostname_filefile_hostname_inforU  s       r   r  z&DefaultOSUtil._get_cloud_init_hostname(  s     ;	Kww~~m, :MJ-- 5$(IIe$4M5.(44 5 5  	KKK8$y/JJ	Ks0   AA9 A-A9 -A62A9 9	B+B&&B+c                     | j                  |      rt        j                  d|       | j                  ddg       | j                  ddd|g       | j	                  |d       y )	Nz){0} is a system user. Will not delete it.touchz/var/run/utmpuserdelz-fz-rT)r   )r   r   r   r]  r   )rP   r   s     r   del_accountzDefaultOSUtil.del_accountC  s\    H%LLDhO))7O*DE))9dD(*KL$/r   c                 J    t        j                  |      j                  d      S )Nzutf-8)base64	b64decoder  )rP   datas     r   decode_customdatazDefaultOSUtil.decode_customdataK  s    %,,W55r   c                 ^    t        j                  d      t        j                  d      z  dz  S )NSC_PAGE_SIZESC_PHYS_PAGES   )r   sysconfrO   s    r   get_total_memzDefaultOSUtil.get_total_memN  s$    zz.)BJJ,GG9UUr   c                 *    t        j                         S r   )multiprocessing	cpu_countrO   s    r   get_processor_coresz!DefaultOSUtil.get_processor_coresR  s    ((**r   c                     	 t        |      }t        j                  |d       y# t        t        f$ r Y yt
        $ r,}|j                  t        j                  k(  rY d }~yY d }~yd }~ww xY w)Nr   FT)rf   r   kill
ValueError	TypeErrorr  errnoEPERM)rP   pidos_errors      r   check_pid_alivezDefaultOSUtil.check_pid_aliveU  sZ    	c(CGGCO  I& 	 	~~,	s   !$ A)A)A$$A)c                 (    t         j                  dkD  S )Nl        )sysmaxsizerO   s    r   is_64bitzDefaultOSUtil.is_64bita  s    {{W$$r   c                      d} 	 t        j                  d      } | S # t        t        f$ r4}t	        j
                  dj                  |j                                d}~ww xY w)aE  
        Get the contents of /proc/stat.
        # cpu  813599 3940 909253 154538746 874851 0 6589 0 0 0
        # cpu0 401094 1516 453006 77276738 452939 0 3312 0 0 0
        # cpu1 412505 2423 456246 77262007 421912 0 3276 0 0 0

        :return: A single string with the contents of /proc/stat
        :rtype: str
        Nz
/proc/statzCouldn't read /proc/stat: {0})r   r   r  r   r   rk   rc   strerror)resultsexs     r   _get_proc_statzDefaultOSUtil._get_proc_state  s[     	((6G
 	 ! 	KK7>>r{{KL	s    A/AAc                      d} t         j                         }|P|j                         D ]=  }t        j	                  |      st        d |j                         dd D              }  | S  | S )z
        Compute the number of USER_HZ units of time that have elapsed in all categories, across all cores, since boot.

        :return: int
        r   c              3   2   K   | ]  }t        |        y wr   )rf   ).0r}   s     r   	<genexpr>z?DefaultOSUtil.get_total_cpu_ticks_since_boot.<locals>.<genexpr>  s      %;#$A%;s   r   r  )rG   r  r
  ALL_CPUS_REGEXre   sumrd   )
system_cpu	proc_statro   s      r   get_total_cpu_ticks_since_bootz,DefaultOSUtil.get_total_cpu_ticks_since_booty  sx     
!002	 !,,. !''-!$ %;(,

Qq(9%; ";J
 r   c                      dx} }ddg}t        j                  |      }|j                  d      D ]D  }t        j	                  |      s|j                         }t        |d         } t        |d         }F | dz  |dz  fS )ak  
        Get the contents of free -b in bytes.
        # free -b
        #              total        used        free      shared  buff/cache   available
        # Mem:     8340144128   619352064  5236809728     1499136  2483982336  7426314240
        # Swap:             0           0           0

        :return: used and available memory in megabytes
        r   freez-brY   rz      r  )r   r_   rd   ALL_MEMS_REGEXre   rf   )used_memavailable_memfree_cmdmemoryro   memss         r   $get_used_and_available_system_memoryz2DefaultOSUtil.get_used_and_available_system_memory  s     $%$=D>&&x0LL& 	-D##D)zz|tAw< #DG		-
 #]I%>>>r   c                    i }g d}g d}g d}	 t        j                  |      }|r)d } ||      }	 ||      }
dj                  ||||	||
      S | j                  ||       | j                  ||t        j                  d	       | j                  ||t        j                  d
       |S # t         j                  $ r/}t        j                  dt        |             |rdni cY d}~S d}~ww xY w)a%  
        Capture NIC state (IPv4 and IPv6 addresses plus link state).

        :return: By default returns a dictionary of NIC state objects, with the NIC name as key. If as_string is True
                 returns the state as a string
        :rtype: dict(str,NetworkInformationCard)
        )r  -arA  link)r  z-4r  rA  address)r  z-6r  rA  r  z"Could not fetch NIC link info: {0}rt   Nc                     	 t        j                  |       S # t         j                  $ r}t        |      cY d }~S d }~ww xY wr   )r   r_   r   r?   )r   command_errors     r   r_   z0DefaultOSUtil.get_nic_state.<locals>.run_command  s9    .$0099 -- .}--.s    ?
:??z9Executing {0}:
{1}
Executing {2}:
{3}
Executing {4}:
{5}
zan IPv4 addresszan IPv6 address)r   r_   r   r   r   r   rc   _update_nic_state_all_update_nic_stater   add_ipv4add_ipv6)rP   	as_stringstateall_commandinet_commandinet6_command
all_outputr  r_   inet_outputinet6_outputs              r   get_nic_statezDefaultOSUtil.get_nic_state  s    0:;	+"..{;J
 . &l3K&}5LT[[\gis  vB  DO  Q^  `l  m  m&&uj9""5,8L8U8UWhi""5-9M9V9VXijL' %% 	+NN?mATU"2*	+s   B( (C*;$C%C*%C*c                     |j                         D ]I  }t        j                  |      }|s|j                  d      }t	        ||j                  d            | |<   K y )Nr   rz   )r
  IP_COMMAND_OUTPUTre   rg   r   )r  command_outputr  r  names        r   r  z#DefaultOSUtil._update_nic_state_all  sV    #..0 	JE
 ',,U3F||A24aId	Jr   c                    	 t        j                  |      }|j                         D ]p  }t        j	                  |      }|s|j                  d      }|| v r || |   |j                  d             Lt        j                  dj                  ||             r y# t         j                  $ r9}t        j                  ddj                  |      t        |             Y d}~yd}~ww xY w)a  
        Update the state of NICs based on the output of a specified ip subcommand.

        :param dict(str, NetworkInterfaceCard) state: Dictionary of NIC state objects
        :param str ip_command: The ip command to run
        :param handler: A method on the NetworkInterfaceCard class
        :param str description: Description of the particular information being added to the state
        r   rz   z'Interface {0} has {1} but no link statez[{0}] failed: {1}r  N)r   r_   r
  r  re   rg   r   r   rc   r   r   r?   )	r  
ip_commandhandlerdescriptionrm   r  r  interface_namer  s	            r   r  zDefaultOSUtil._update_nic_state  s    	X**:6F**, t +007%+\\!_N%.n 5v||AG%N%U%UVdfq%rst  %% 	XLL,chhz.BCDVWW	Xs   ?B AB C'./C""C'c                 R    	 t        j                  | |       y # t        $ r Y y w xY wNr!  r   r_   rh   )r   r"  s     r   r]  z*DefaultOSUtil._run_command_without_raising  s)    	!!#; 		s    	&&c                 j    | D ]  }	 t        j                  ||        y # t        $ r |rY +Y  y w xY wr  r  )commandsr"  continue_on_errorr   s       r   &_run_multiple_commands_without_raisingz4DefaultOSUtil._run_multiple_commands_without_raising  s@     	C%%cY?	  $s   !22c           
      B   	 t        j                  | d|      S # t         j                  $ r@}t        dj	                  ||j
                  |j                  |j                              d }~wt        $ r*}t        dj	                  |dt        |                  d }~ww xY w)NT)r"  inputz*{0}, Retcode: {1}, Output: {2}, Error: {3}z{0}, Retcode: {1}, Error: {2}r\   )
r   r_   r   r
   rc   rj   rZ  r[  rh   r   )r   r   	cmd_inputrq   s       r   r   z.DefaultOSUtil._run_command_raising_OSUtilError  s    	\((INN%% 	p<CCGQ\\[\[c[cefememnp p 	\=DDWbRVWXRYZ[[	\s     B;A((B4%BBr   )NN)r  
   )FF)z/dev)r  TNN   )TN)T)r   r4  )rZ   r  )F)TF)k__name__
__module____qualname__rQ   staticmethodrM   rU   rW   rr   r^   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  r   r5  r>  rQ  rT  r\  r_  r^  ra  r@  rS  rk  ru  rx  r  r{  r  r  r  r  r  r  r  r  r  r  r  r#  rz  r(  r.  r2  r5  r7  r9  r<  r>  r@  rB  rD  rF  rH  rN  rR  rV  rZ  r_  re  rk  rn  rs  rq  rD  r  r  r  rm  r  r  r  r  r  r  r  propertyr  r  r  r  r  r  r  r]  r  r   r   r   r   rG   rG      s   4   % %  !F(Y0v(4T  6	M)4"  2q&iPB	N  ",6$$L	 
P	. !"'GRY'$FB$ %''2
U  >$    D     &+!Z6 ; ;z
& . .  9SP8 <
*( " "" ( (T&N  406V+
 % %  &    ? ?(#J 	J 	J X X>     \ \r   rG   )Er  r  r  r  r	  r  r  r   r  r   r`   r   r  r  r  rF  r   r  azurelinuxagent.commonr   r   azurelinuxagent.common.utilsr   r   r	    azurelinuxagent.common.exceptionr
   azurelinuxagent.common.futurer   r   &azurelinuxagent.common.utils.cryptutilr   -azurelinuxagent.common.utils.flexible_versionr   (azurelinuxagent.common.utils.networkutilr   r   r   &azurelinuxagent.common.utils.shellutilr   rn  ra   ru   rv   r   r   r'   r*   r9   r<   rA   rD   rb   r  r  r]   r   r   
IGNORECASEr   r  r  r  r  r  r}  r  objectrG   r   r   r   <module>r     sX  &        	  
 	    
    ' ) 1 2 1 8 > < I g g ?H>@ 'BJJ'?@ +H5 %IgCiL
A <I&H% 02rzz<MM    BJJ89 / 7H\F H\r   