U
    LdU                     @   s   d 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 ddlmZmZ e	eZdZdd	 Zeed
ddZeje dddZdd Zdd Zdd Zdd Zdd ZG dd de
jZ e e
j!ffgZ"dd Z#dS )zr
This file contains code used to gather the user data passed to an
instance on rootbox / hyperone cloud platforms
    N)IPv4Address)log)sourcessubputil)
EventScope	EventTypez
/etc/hostsc                  C   s.   t jtdd} | r td dS td dS )NT)quietz5/etc/hosts exists - setting manage_etc_hosts to FalseFz=/etc/hosts does not exists - setting manage_etc_hosts to True)r   	load_file	ETC_HOSTSLOGdebug)Zhosts r   F/usr/lib/python3/dist-packages/cloudinit/sources/DataSourceRbxCloud.pyget_manage_etc_hosts   s    

r   )increturnc                 C   s   t ttt| | S N)strr   int)addrr   r   r   r   increment_ip#   s    r   )r   c                 C   s   | t | dt | dgS )zReturn a list of 3 IP addresses: [addr, addr + 2, addr + 3]

    @param addr: an object that is passed to IPvAddress
    @return: list of strings
          )r   )r   r   r   r   get_three_ips'   s    r   c                 C   s   t  dg|  S )z
    Uses the preferred cloud-init subprocess def of subp.subp
    and runs arping.  Breaking this to a separate function
    for later use in mocking and unittests
    Zarping)r   )cmdr   r   r   _sub_arp4   s    r   c                 C   s|   d}|j dkrd}| D ]`}ztdd||d |d g W q tjk
rt } ztd|d |d | W 5 d }~X Y qX qd S )	Nz-S)ZfedoraZcentosZrhelz-sz-c2sourcedestinationz&Failed to arping from "%s" to "%s": %s)namer   r   ZProcessExecutionErrorr   Zwarning)itemsdistroZsource_paramitemerrorr   r   r   gratuitous_arp=   s    
r%   c                  C   s   t tdtd } | s dS | D ]}z(tj|tdddgd}|rN|W   S W q$ tk
r } z|jtjkrp W 5 d}~X Y q$ tjk
r   t	t
d	| Y q$X q$t
d
d|  dS )zAReturns False (not found or error) or a dictionary with metadata.zLABEL=CLOUDMDzLABEL=cloudmdFZvfatZfatZmsdosfs)devicecallbackZmtypeNz-Failed to mount %s when looking for user dataz0Did not find RbxCloud data, searched devices: %s,)setr   Zfind_devs_withZmount_cbread_user_data_callbackOSErrorerrnoZENOENTZMountFailedErrorlogexcr   r   join)Zdevicesr&   rbx_dataerrr   r   r   get_mdR   s<       r1   c                 C   s   ddd t | D dS )zGenerate network configuration

    @param netadps: A list of network adapter settings

    @returns: A dict containing network config
       c                    sB   g | ]:\} d d t| d   fdd d D dqS )Zphysicalzeth{}Z
macaddressc              	      s>   g | ]6}d |d  d d d d d  d d d dqS )	ZstaticaddressnetworknetmaskautogatewayZdnsZnameservers)typer3   r5   Zcontrolr7   Zdns_nameserversr   ).0ipnetadpr   r   
<listcomp>   s   


z6generate_network_config.<locals>.<listcomp>.<listcomp>r:   )r8   r    Zmac_addressZsubnets)formatr   lower)r9   ir   r;   r   r=   z   s   

z+generate_network_config.<locals>.<listcomp>)versionZconfig)	enumerate)Znetadpsr   r   r   generate_network_configq   s
    rC   c                 C   s  t jt jtj| dddd}t jtj| ddd}d|ksHd	|krXt td
 dS |di d}|di dg }d}|di dr|d d d }t	|d	 }||d d |d d g ddd |d	 D ddd||dg|d|di|t
 dd}td t| |S )a   This callback will be applied by util.mount_cb() on the mounted
    drive.

    @param mount_dir: String representing path of directory where mounted drive
    is available

    @returns: A dict containing userdata, metadata and cfg based on metadata.
    z
cloud.jsonF)fnamedecode)textz	user.dataT)rD   r	   Zvmr<   z(Failed to load metadata. Invalid format.NZadditionalMetadatausernameZsshKeysZpasswordZsha512Z_idr    )zinstance-idzlocal-hostnamepublic-keysc                 S   s>   g | ]6}|d  D ](}t |d d D ]}|d |dq$qqS )r:   r4   r7   r3   )r   r   )r   )r9   r<   r:   targetr   r   r   r=      s   
  z+read_user_data_callback.<locals>.<listcomp>Zdefault_userzALL=(ALL) NOPASSWD:ALL)r    ZgecosZsudoZpasswdZlock_passwdZssh_authorized_keys)Z
ssh_pwauthZdisable_rootZsystem_infonetwork_configZmanage_etc_hosts)userdatametadatar%   cfgzreturning DATA object:)r   Z	load_jsonr
   ospathr.   r-   r   getrC   r   r   )Z	mount_dirZ	meta_dataZ	user_datarG   Zssh_keyshashr4   datar   r   r   r*      sZ    	  




r*   c                   @   sj   e Zd ZdZejejejej	hiZ
dd Zdd Zdd Zedd	 Zd
d Zdd Zdd Zdd ZdS )DataSourceRbxCloudZRbxCloudc                 C   s   t j| ||| d | _d S r   )r   
DataSource__init__seed)selfZsys_cfgr"   pathsr   r   r   rU      s    zDataSourceRbxCloud.__init__c                 C   s   t j| }d|| jf S )Nz%s [seed=%s])r   rT   __str__rV   )rW   rootr   r   r   rY      s    zDataSourceRbxCloud.__str__c                 C   s>   t  }|dkrdS |d | _|d | _|d | _|d | _dS )zw
        Metadata is passed to the launching instance which
        is used to perform instance configuration.
        FrK   rL   r%   rM   T)r1   userdata_rawrL   r%   rM   )rW   r/   r   r   r   	_get_data   s    



zDataSourceRbxCloud._get_datac                 C   s
   | j d S )NrJ   rM   rW   r   r   r   rJ      s    z!DataSourceRbxCloud.network_configc                 C   s
   | j d S )NrH   )rL   r^   r   r   r   get_public_ssh_keys   s    z&DataSourceRbxCloud.get_public_ssh_keysc                 C   s   | j S r   )r[   r^   r   r   r   get_userdata_raw   s    z#DataSourceRbxCloud.get_userdata_rawc                 C   s   | j S r   r]   r^   r   r   r   get_config_obj   s    z!DataSourceRbxCloud.get_config_objc                 C   s   t | j | j d S r   )r%   r"   )rW   rM   Zis_new_instancer   r   r   activate  s    zDataSourceRbxCloud.activateN)__name__
__module____qualname__Zdsnamer   ZNETWORKr   ZBOOT_NEW_INSTANCEZBOOTZBOOT_LEGACYZdefault_update_eventsrU   rY   r\   propertyrJ   r_   r`   ra   rb   r   r   r   r   rS      s    
rS   c                 C   s   t | tS r   )r   Zlist_from_dependsdatasources)Zdependsr   r   r   get_datasource_list  s    rh   )$__doc__r,   rN   os.pathtypingZ	ipaddressr   Z	cloudinitr   Zloggingr   r   r   Zcloudinit.eventr   r   Z	getLoggerrc   r   r   r   r   r   r   ZListr   r   r%   r1   rC   r*   rT   rS   ZDEP_FILESYSTEMrg   rh   r   r   r   r   <module>   s,   
		!B3
