
"T`*                 @   s   d  Z  d d l m Z d d l m Z d d l m Z d d l Z d g Z e j e	  Z
 d Z d d	   Z d
 d   Z d d   Z d d   Z d d d d  Z d S)a  
LXD
---
**Summary:** configure lxd with ``lxd init`` and optionally lxd-bridge

This module configures lxd with user specified options using ``lxd init``.
If lxd is not present on the system but lxd configuration is provided, then
lxd will be installed. If the selected storage backend is zfs, then zfs will
be installed if missing. If network bridge configuration is provided, then
lxd-bridge will be configured accordingly.

**Internal name:** ``cc_lxd``

**Module frequency:** per instance

**Supported distros:** ubuntu

**Config keys**::

    lxd:
        init:
            network_address: <ip addr>
            network_port: <port>
            storage_backend: <zfs/dir>
            storage_create_device: <dev>
            storage_create_loop: <size>
            storage_pool: <name>
            trust_password: <password>
        bridge:
            mode: <new, existing or none>
            name: <name>
            ipv4_address: <ip addr>
            ipv4_netmask: <cidr>
            ipv4_dhcp_first: <ip addr>
            ipv4_dhcp_last: <ip addr>
            ipv4_dhcp_leases: <size>
            ipv4_nat: <bool>
            ipv6_address: <ip addr>
            ipv6_netmask: <cidr>
            ipv6_nat: <bool>
            domain: <domain>
    )log)subp)utilNZubuntuZlxdbr0c             C   s  | j  d  } | s) | j d |   d  St | t  sR | j d t |   d  S| j  d  } t | t  s | j d t |   i  } | j  d i   } t | t  s | j d t |   i  } g  } t j d  s | j d  | j  d  d	 k rt j d	  r| j d
  t	 |  ry | j
 j |  Wn? t j k
 r~}	 z | j d | |	  d  SWYd  d  }	 ~	 Xn X| rd+ }
 t j d d d g  d d d g } xM |
 D]E } | j  |  r| j d | j d d  t | |  f g  qWt j |  d } | r| j  d t  } t j j d  rt j |  rt |  } yN | j d |  d j d d   | j   D  d } t j d g |  Wn& t k
 rt j | d |  Yn Xt j d  | j d   t j d! d d" g  qt |  \ } } t d# | d$ t |  d% t |  d& t |   | ro| j d' d( j |   t |  | r| j d) d( j |   t |  n | rt d* |   d  S),NZlxdz8Skipping module named %s, not present or disabled by cfgz-lxd config must be a dictionary. found a '%s'Zinitz2lxd/init config must be a dictionary. found a '%s'Zbridgez4lxd/bridge config must be a dictionary. found a '%s'storage_backendZzfszzfsutils-linuxz!failed to install packages %s: %snetwork_addressnetwork_portstorage_create_devicestorage_create_loopstorage_pooltrust_passwordZ	waitreadyz--timeout=300z--autoz--%s=%s_-zdebconf-communicatenamez/etc/default/lxd-bridgezSetting lxd debconf via 
c             S   s&   g  |  ] \ } } d  | | f  q S)z	set %s %s ).0kvr   r   9/usr/lib/python3/dist-packages/cloudinit/config/cc_lxd.py
<listcomp>   s   	zhandle.<locals>.<listcomp>zFailed to run '%s' for lxd withz Running dpkg-reconfigure for lxdzdpkg-reconfigurez--frontend=noninteractivenet_namedid_initcreateattachzCreating lxd bridge: %s z!Setting up default lxd bridge: %sz*Unable to configure lxd bridge without %s.)r   r   r   r   r	   r
   r   ) getdebug
isinstancedictZwarningtyper   ZwhichappendlenZdistroZinstall_packagesProcessExecutionErrorextendreplacestr_DEFAULT_NETWORK_NAMEospathexistsbridge_to_debconfjoinitems	Exceptionr   ZlogexcZdel_filebridge_to_cmdmaybe_cleanup_defaultbool_lxcRuntimeError)r   ZcfgZcloudr   argsZlxd_cfgZinit_cfg
bridge_cfgZpackagesexcZ	init_keyscmdr   Z
dconf_commr   debconfdata
cmd_create
cmd_attachr   r   r   handle>   s    				%  	+	
	r;   c             C   s  i  } |  j  d  d k r2 d | d <d | d <n|  j  d  d k rq d | d <d | d	 <|  j  d
  | d <nb|  j  d  d k rd | d <|  j  d
  r |  j  d
  | d <|  j  d  r@d | d <|  j  d  | d <|  j  d  | d <|  j  d  | d <|  j  d  | d <|  j  d  | d <|  j  d d  | d <|  j  d  rd | d <|  j  d  | d <|  j  d  | d <|  j  d d  | d <|  j  d   r|  j  d   | d! <n t d" |  j  d    | S)#Nmodenonefalsezlxd/setup-bridge zlxd/bridge-nameexistingtruezlxd/use-existing-bridger   newipv4_addresszlxd/bridge-ipv4zlxd/bridge-ipv4-addressipv4_netmaskzlxd/bridge-ipv4-netmaskipv4_dhcp_firstzlxd/bridge-ipv4-dhcp-firstipv4_dhcp_lastzlxd/bridge-ipv4-dhcp-lastZipv4_dhcp_leaseszlxd/bridge-ipv4-dhcp-leasesipv4_natzlxd/bridge-ipv4-natipv6_addresszlxd/bridge-ipv6zlxd/bridge-ipv6-addressipv6_netmaskzlxd/bridge-ipv6-netmaskipv6_natzlxd/bridge-ipv6-natdomainzlxd/bridge-domainzinvalid bridge mode "%s")r   r-   )r4   r7   r   r   r   r*      s:    





r*   c             C   s  |  j  d  d k r d  S|  j  d t  } g  } d d | d d g } |  j  d  d k re d  | f S|  j  d  d	 k r t d
 |  j  d    d d | g } |  j  d  rb|  j  d  rb| j d |  j  d  |  j  d  f  |  j  d d  d k r| j d  |  j  d  ro|  j  d  rod |  j  d  |  j  d  f } | j d |  n | j d  |  j  d  r|  j  d  r| j d |  j  d  |  j  d  f  |  j  d d  d k r| j d  n | j d  |  j  d  r| j d |  j  d   | | f S)!Nr<   r=   r   networkzattach-profiledefaulteth0r@   rB   zinvalid bridge mode "%s"r   rC   rD   zipv4.address=%s/%srG   rA   zipv4.nat=truerE   rF   z%s-%szipv4.dhcp.ranges=%szipv4.address=nonerH   rI   zipv6.address=%s/%srJ   r>   zipv6.nat=truezipv6.address=nonerK   zdns.domain=%s)NN)r   r&   r-   r    )r4   Zbridge_namer9   r:   Z
dhcp_ranger   r   r   r.      sB    	
		r.   c             C   sa   d d d t  j j d d  d t  j j d d  i } t j d g t |   d g d	 | d  S)
NLC_ALLCHOMEz/rootZUSERrootZlxcz--force-localZ
update_env)r'   environr   r   list)r6   envr   r   r   r1     s    r1   rM   rN   c       
      C   sz  |  t  k s | r d Sd } d } | r d } y0 t d d |  | g  t j | |  | |  WnS t j k
 r }	 z0 |	 j d k r |	  t j | |  | |  WYd d }	 ~	 Xn- Xd } t d d	 |  g  t j | |  |  | rvd
 } y3 t d d d | | g  t j | | | |  WnS t j k
 ru}	 z0 |	 j d k rM|	  t j | | | |  WYd d }	 ~	 Xn Xd S)zNewer versions of lxc (3.0.1+) create a lxdbr0 network when
    'lxd init --auto' is run.  Older versions did not.

    By removing ay that lxd-init created, we simply leave the add/attach
    code in-tact.

    https://github.com/lxc/lxd/issues/4649Nz"failed. Assuming it did not exist.z
succeeded.z/Detach of lxd network '%s' from profile '%s' %srL   zdetach-profile   zDeletion of lxd network '%s' %sZdeletez+Removal of device '%s' from profile '%s' %sprofileZdeviceremove)r&   r1   LOGr   r   r"   Z	exit_code)
r   r   r   r   rW   Znic_nameZfail_assume_enoentZ	succeededmsger   r   r   r/     s2    	)r/   )__doc__Z	cloudinitr   Zloggingr   r   r'   ZdistrosZ	getLogger__name__rY   r&   r;   r*   r.   r1   r/   r   r   r   r   <module>0   s   	f22