HEX
Server: Apache
System: Linux server2.voipitup.com.au 4.18.0-553.104.1.lve.el8.x86_64 #1 SMP Tue Feb 10 20:07:30 UTC 2026 x86_64
User: posscale (1027)
PHP: 8.2.29
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //opt/saltstack/salt/lib/python3.10/site-packages/salt/cloud/clouds/__pycache__/ec2.cpython-310.pyc
o

�N�g,q�@s�dZddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
ZddlZddlmmZddlmZddlmZddlZddlmmZddlZddlZddlZddl Zddl!mm"Z"ddl#Zddl$Zddl%Zddl&Zddl'm(Z(m)Z)m*Z*m+Z+m,Z,zddl-Z-dZ.Wne/y�dZ.Ynwe�0e1�Z2ddd	d
ddd
ddddd�Z3dZ4dZ5gd�Z6e
�7de
j8�Z9dZ:dd�Z;dd�Z<dd�Z=dd�Z>d d!�Z?d"d#�Z@d$d%�ZA						d�d&d'�ZB			(	)	*	+d�d,d-�ZCd�d.d/�ZDd�d0d1�ZEd2d3�ZFd4d5�ZGd6d7�ZHd8d9�ZId:d;�ZJd<d=�ZKd�d>d?�ZLd�d@dA�ZMdBdC�ZNdDdE�ZOdFdG�ZPdHdI�ZQdJdK�ZRdLdM�ZSdNdO�ZTdPdQ�ZUdRdS�ZVd�dTdU�ZWd�dVdW�ZXdXdY�ZYdZd[�ZZd\d]�Z[d^d_�Z\d`da�Z]dbdc�Z^d�ddde�Z_d�dfdg�Z`d�dhdi�Zadjdk�Zbd�dldm�Zcd�dndo�Zd					d�dpdq�Zedrds�Zfd�dtdu�Zgdvdw�Zhd�dxdy�Zid�dzd{�Zjd�d|d}�Zk							d�d~d�Zl	d�d�d��Zm	d�d�d��Znd�d�d��Zod�d�d��Zpd�d�d��Zqd�d�d��Zrd�d�d��Zsd�d�d��Ztd�d�d��Zud�d��Zvd�d��Zwd�d�d��Zxd�d�d��Zyd�d�d��Zzd�d�d��Z{d�d�d��Z|d�d�d��Z}d�d��Z~d�d�d��Zd�d�d��Z�d�d�d��Z�d�d�d��Z�d�d�d��Z�d�d�d��Z�d�d�d��Z�						d�d�d��Z�d�d�d��Z�d�d��Z�d�d��Z�d�d�d��Z�d�d��Z�d�d�d��Z�d�d�d��Z�d�d�dÄZ�d�d�dńZ�d�dDŽZ�d�d�dɄZ�d�d�d˄Z�d�d�d̈́Z�d�d�dτZ�d�d�dфZ�d�d�dӄZ�d�d�dՄZ�d�d�dׄZ�d�d�dلZ�					d�d�dۄZ�				d�d�d݄Z�d�d�d߄Z�d�d�Z�d�d�d�Z�d�d�d�Z�d�d�d�Z�dS)�a�	
The EC2 Cloud Module
====================

The EC2 cloud module is used to interact with the Amazon Elastic Compute Cloud.

To use the EC2 cloud module, set up the cloud configuration at
 ``/etc/salt/cloud.providers`` or ``/etc/salt/cloud.providers.d/ec2.conf``:

.. code-block:: yaml

    my-ec2-config:
      # EC2 API credentials: Access Key ID and Secret Access Key.
      # Alternatively, to use IAM Instance Role credentials available via
      # EC2 metadata set both id and key to 'use-instance-role-credentials'
      id: GKTADJGHEIQSXMKKRBJ08H
      key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs

      # If 'role_arn' is specified the above credentials are used to
      # to assume to the role. By default, role_arn is set to None.
      role_arn: arn:aws:iam::012345678910:role/SomeRoleName

      # The ssh keyname to use
      keyname: default
      # The amazon security group
      securitygroup: ssh_open
      # The location of the private key which corresponds to the keyname
      private_key: /root/default.pem

      # Be default, service_url is set to amazonaws.com. If you are using this
      # driver for something other than Amazon EC2, change it here:
      service_url: amazonaws.com

      # The endpoint that is ultimately used is usually formed using the region
      # and the service_url. If you would like to override that entirely, you
      # can explicitly define the endpoint:
      endpoint: myendpoint.example.com:1138/services/Cloud

      # SSH Gateways can be used with this provider. Gateways can be used
      # when a salt-master is not on the same private network as the instance
      # that is being deployed.

      # Defaults to None
      # Required
      ssh_gateway: gateway.example.com

      # Defaults to port 22
      # Optional
      ssh_gateway_port: 22

      # Defaults to root
      # Optional
      ssh_gateway_username: root

      # Default to nc -q0 %h %p
      # Optional
      ssh_gateway_command: "-W %h:%p"

      # One authentication method is required. If both
      # are specified, Private key wins.

      # Private key defaults to None
      ssh_gateway_private_key: /path/to/key.pem

      # Password defaults to None
      ssh_gateway_password: ExamplePasswordHere

      driver: ec2

      # Pass userdata to the instance to be created
      userdata_file: /etc/salt/my-userdata-file

      # Instance termination protection setting
      # Default is disabled
      termination_protection: False

:depends: requests
�N)�
cmp_to_key)�SaltCloudConfigError�SaltCloudException�SaltCloudExecutionFailure�SaltCloudExecutionTimeout�SaltCloudSystemExitTFZec2_ap_northeastZec2_ap_northeast_2Zec2_ap_southeastZec2_ap_southeast_2Zec2_eu_westZec2_eu_centralZec2_sa_eastZec2_us_eastZec2_us_gov_west_1Zec2_us_westZec2_us_west_oregon)zap-northeast-1zap-northeast-2zap-southeast-1zap-southeast-2z	eu-west-1zeu-central-1z	sa-east-1�	us-east-1z
us-gov-west-1z	us-west-1z	us-west-2rz
2016-11-15)ZRequestLimitExceededZInsufficientInstanceCapacityZ
InternalErrorZUnavailableZInsufficientAddressCapacityZ$InsufficientReservedInstanceCapacityz	/\*.*?\*/�ec2cCs t�durdSt�durdStS)zH
    Set up the libcloud functions and check for EC2 configurations
    F)�get_configured_provider�get_dependencies�__virtualname__�r
r
�I/opt/saltstack/salt/lib/python3.10/site-packages/salt/cloud/clouds/ec2.py�__virtual__�s


rcCs"zt��WStytYSw�N)Z__active_provider_name__�value�AttributeErrorr
r
r
r�_get_active_provider_name�s

�rcCst�tt�ptd�S)z/
    Return the first configured instance.
    )�id�key)�configZis_provider_configured�__opts__rrr
r
r
rr
�s�r
cCsttjjd�}t�t|�S)z*
    Warn if dependencies aren't met.
    )�requestsZcryptography)�HAS_REQUESTS�salt�crypt�HAS_CRYPTOGRAPHYrZcheck_driver_dependenciesr)Zdepsr
r
rr�s�rcCs�t|�dkr|j}d|vr|�d�}|d}||jiSi}|D]H}|j}d|vr1|�d�}|d}||vrHt|�dkrBt|�||<q|j||<qt||t�s^||}g||<||�|�||�t|��q|S)z)
    Convert an XML tree into a dict
    ��}r)�len�tag�split�text�_xml_to_dict�
isinstance�list�append)Zxmltree�name�compsZxmldict�itemZtempvarr
r
rr#�s,


r#cCs�i}i}|��D]3\}}d|vrt|d<|d|vr i||d<|d|df}|||dvr;||d�||d|<q|��D]!\}}|��D]\}}|\}}	|d}
|d}|
|vr`|||
<qHq@|S)a4
    Return an optimized list of providers.

    We want to reduce the duplication of querying
    the same region.

    If a provider is using the same credentials for the same region
    the same data will be returned for each provider, thus causing
    un-wanted duplicate data and API calls to EC2.

    �locationrr)r'�datar'r+)�items�DEFAULT_LOCATION)Z	providersZ
tmp_providersZoptimized_providersr'r+�credsr*Ztmp_dataZ_idZ_key�_name�_datar
r
r�optimize_providers�s.����r1cCst�||�d�tj���S)N�utf-8)�hmac�new�encode�hashlib�sha256�digest)r�msgr
r
r�signsr:c6
Cs�t�}|�dd�}t�|�\}}	}
d}|tjk�r�|��}tj���d�}
|s*t	�}|sM|�dd|�d|���}d|�d	�}t
j�|�j
}t
j�|�j}n*t
j�|�j
}t
j�|�j}|d
krwd�|�}t�|�|dursd
|i|fSd
|iSt�d|�d}|}d}t
j�|�j}|��}tj��}|�d�}|�d�}d|dd|d}d}tjj�d
�}|�dt�}||d<tt|��}t|j|�}t
j�tt||���}|�dd�}|d|d|d|d|d|} d}!|d	|d	|d	d}"|!d|d|"dtjj�| �}#td|d� d�|�}$t|$|�}%t|%|�}&t|&d�}'t!�"|'|#� d�t#j$��%�}(|!d d!|d"d	|"d#d$|d#d%|(})||)d&�}*t�d'|�t�&d(|�zt'j||*|d)d*�}+t�d+|+j(�t�&d,|+j)�|+�*�Wn�t'j+j,�y�},z`t-�.|,j/j0�}-t1|-�}.|.�d-i��d.i��d/d
�}/|/�r�|/t2v�r�|d07}t�d1|,j/j(|,|.|�t�3|�WYd},~,qt�d2|,j/j(|,|.�|du�r�d
|.i|fWYd},~,Sd
|.iWYd},~,Sd},~,wwt�d2|,j/j(|,|.�|du�rd
|.i|fSd
|.iS|+j)}0t-�.|0�}-|-d0}1|du�r|-}1|�r<t4|-�D]\}2}3|3j5�6d3�}4|4d0|k�r:|-|2}1�q%g}5|1D]
}3|5�7t1|3���q@|du�rT|5|fS|5S)4N�service_urlz
amazonaws.comrz%Y-%m-%dT%H:%M:%SZ�endpointzec2.�.zhttps://�/�zqCould not find a valid endpoint in the requesturl: {}. Looking for something like https://some.ec2.endpoint/?argsT�errorzUsing EC2 endpoint: %sZGETr	z%Y%m%dT%H%M%SZz%Y%m%dzhost:�
zx-amz-date:zhost;x-amz-date�ec2_api_versionZVersion�+z%20zAWS4-HMAC-SHA256Zaws4_requestZAWS4rr2� zCredential=rz, zSignedHeaders=z
Signature=)z
x-amz-dateZ
AuthorizationzEC2 Request: %szEC2 Request Parameters: %s�x)�headers�params�timeoutzEC2 Response Status Code: %szEC2 Response Text: %s�Errors�ErrorZCoderzFEC2 Response Status Code and Error: [%s %s] %s; Attempts remaining: %sz.EC2 Response Status Code and Error: [%s %s] %sr)8r
�get�awsr.�AWS_MAX_RETRIES�copy�datetime�utcnow�strftime�get_location�urllib�parse�urlparse�netloc�path�format�logr@�debug�stripr�utilsZ	hashutilsZ
sha256_digest�DEFAULT_EC2_API_VERSION�sortedr%�map�	urlencode�zip�replacer:r5r3r4r6r7�	hexdigest�tracerZstatus_coder"Zraise_for_status�
exceptions�	HTTPError�ETZ
fromstring�response�contentr#�EC2_RETRY_CODES�sleep_exponential_backoff�	enumerater r!r&)6rG�setname�
requesturlr*�
return_url�return_root�providerr;Z
access_key_idZsecret_access_key�token�attemptsZparams_with_headers�	timestampr<Z
endpoint_pathZendpoint_err�method�regionZserviceZ
canonical_uri�host�tZamz_dateZ	datestampZcanonical_headersZsigned_headersZpayload_hashrB�keys�valuesZquerystringZcanonical_request�	algorithmZcredential_scopeZstring_to_signZkDateZkRegionZkServiceZsigning_keyZ	signatureZauthorization_headerrF�result�exc�rootr+Zerr_coderhr,�idxr)r(�retr
r
r�querysh	�



��������	�
����������



����������	�
���
���
�
���


�
r��X�r�
c	Cs�|durd}|duri}|}	t�dt|d�t|d��||i|��}|dur<t�d|�|d8}|d	kr;td
��n|durB|S|d	krVtd�t|d�t|d����t�|�||8}|dkru||9}||kro|d}t�d|�q)
a�
    Helper function that waits for a spot instance request to become active
    for a specific maximum amount of time.

    :param update_callback: callback function which queries the cloud provider
                            for spot instance request. It must return None if
                            the required data, running instance included, is
                            not available yet.
    :param update_args: Arguments to pass to update_callback
    :param update_kwargs: Keyword arguments to pass to update_callback
    :param timeout: The maximum amount of time(in seconds) to wait for the IP
                    address.
    :param interval: The looping interval, i.e., the amount of time to sleep
                     before the next iteration.
    :param interval_multiplier: Increase the interval by this multiplier after
                                each request; helps with throttling
    :param max_failures: If update_callback returns ``False`` it's considered
                         query failure. This value is the amount of failures
                         accepted before giving up.
    :returns: The update_callback returned data
    :raises: SaltCloudExecutionTimeout

    Nr
Tz@Waiting for spot instance reservation. Giving up in 00:%02d:%02d�<FzXupdate_callback has returned False which is considered a failure. Remaining Failures: %srrz\Too many failures occurred while waiting for the spot instance reservation to become active.zBUnable to get an active spot instance request for 00:{:02d}:{:02d}z2Interval multiplier in effect; interval is now %ss)	rYrZ�intrrrX�time�sleep�info)	Zupdate_callback�update_argsZ
update_kwargsrH�interval�interval_multiplier�max_failuresZdurationr+r
r
r�_wait_for_spot_instance�sL 

�����
�r�cCs@|dkrtd��ddddd�dd	d
dd�d�d
d
dddd�iddddd�ddddd�ddddd�ddddd�d d!d"d#d�d$dd%dd�d&dd'dd�d(dd)dd�d*dd+dd�d,d-d.d#d�d/�
d0dd1d2d�d3dd4d5d�d6dd7d8d�d9d!d:d;d�d<�d=dd>dd�d?d-d@d#d�dA�dBddCd5d�dDd-dCdEd�dFdGdCdHd�dI�dJddKd2d�dLddMd5d�dNddOd8d�dPd-dQd;d�dR�dSdTdUdVd�dWdXdYdZd�d[d\dCd]d�d^d_dCd2d�d`dadCd5d�dbdcdCd8d�dddedCd;d�dfdgdCdEd�dhdidjdd�dkdldmd2d�dndodpd5d�dqdrdsd8d�dtdud.d;d�dv�
dwdwdxd@d;d�idydydzd{d|d�iid}d}d~dCdd��d�d�d~dCd�d��d�d�d~dCd�d��d�d�ddCd�d��d�d�ddCd�d��d�d�ddCd�d��d�d�ddCd�d��d�d�dd�d�d��d�d�ddd�d��d�d�ddd�d��d�d�ddd�d��d�d�d�d"d�d��d�d�dGd�d�d��d�d�d~d�dd��d�d�dd�dd��d�d�dd�dd��d�d�dd�dd��d��}|S)�z�
    Return a dict of all available VM sizes on the cloud provider with
    relevant data. Latest version can be found at:

    http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html
    �actionz^The avail_sizes function must be called with -f or --function, or with the --list-sizes option�cc2.8xlargez816 (2 x Intel Xeon E5-2670, eight-core with hyperthread)z3360 GiB (4 x 840 GiB)z60.5 GiB)rZcoresZdiskZram�cc1.4xlargez48 (2 x Intel Xeon X5570, quad-core with hyperthread)z1690 GiB (2 x 840 GiB)z22.5 GiB)r�r�zcg1.4xlargezT8 (2 x Intel Xeon X5570, quad-core with hyperthread), plus 2 NVIDIA Tesla M2050 GPUsz1680 GiB (2 x 840 GiB)�c4.large�2zEBS - 500 Mbpsz3.75 GiB�	c4.xlarge�4zEBS - 750 Mbpsz7.5 GiB�
c4.2xlarge�8zEBS - 1000 Mbpsz15 GiB�
c4.4xlargeZ16zEBS - 2000 Mbpsz30 GiB�
c4.8xlargeZ36zEBS - 4000 Mbpsz60 GiB�c3.largez32 GiB (2 x 16 GiB SSD)�	c3.xlargez80 GiB (2 x 40 GiB SSD)�
c3.2xlargez160 GiB (2 x 80 GiB SSD)�
c3.4xlargez320 GiB (2 x 160 GiB SSD)�
c3.8xlargeZ32z640 GiB (2 x 320 GiB SSD))
r�r�r�r�r�r�r�r�r�r��	d2.xlargez"6 TiB (3 x 2 TiB hard disk drives)z30.5 GiB�
d2.2xlargez#12 TiB (6 x 2 TiB hard disk drives)z61 GiB�
d2.4xlargez$24 TiB (12 x 2 TiB hard disk drives)z122 GiB�
d2.8xlargez$24 TiB (24 x 2 TiB hard disk drives)z244 GiB)r�r�r�r��
g2.2xlargez60 GiB (1 x 60 GiB SSD)�
g2.8xlargez240 GiB (2 x 120 GiB SSD))r�r��	p2.xlargeZEBS�
p2.8xlargez488 GiB�p2.16xlargeZ64z732 GiB)r�r�r��	i2.xlargezSSD (1 x 800 GiB)�
i2.2xlargezSSD (2 x 800 GiB)�
i2.4xlargezSSD (4 x 800 GiB)�
i2.8xlargezSSD (8 x 800 GiB))r�r�r�r��x1.16xlargez64 (with 5.45 ECUs each)z1920 GiB (1 x 1920 GiB)z976 GiB�x1.32xlargez128 (with 2.73 ECUs each)z3840 GiB (2 x 1920 GiB)z1952 GiB�r4.largez2 (with 3.45 ECUs each)z	15.25 GiB�	r4.xlargez4 (with 3.35 ECUs each)�
r4.2xlargez8 (with 3.35 ECUs each)�
r4.4xlargez16 (with 3.3 ECUs each)�
r4.8xlargez32 (with 3.1 ECUs each)�r4.16xlargez64 (with 3.05 ECUs each)�r3.largez2 (with 3.25 ECUs each)z32 GiB (1 x 32 GiB SSD)�	r3.xlargez4 (with 3.25 ECUs each)z80 GiB (1 x 80 GiB SSD)�
r3.2xlargez8 (with 3.25 ECUs each)z160 GiB (1 x 160 GiB SSD)�
r3.4xlargez16 (with 3.25 ECUs each)z320 GiB (1 x 320 GiB SSD)�
r3.8xlargez32 (with 3.25 ECUs each))
r�r�r�r�r�r�r�r�r�r�r�r�r�zcr1.8xlargez'16 (2 x Intel Xeon E5-2670, eight-core)zhs1.8xlargez16 (8 cores + 8 hyperthreads)z$48 TiB (24 x 2 TiB hard disk drives)z117 GiBzt2.nano�1z512 MiBzt2.microz1 GiBzt2.smallz2 GiBz	t2.mediumz4 GiBzt2.largez8 GiBz	t2.xlargez16 GiBz
t2.2xlargez32 GiBzm4.largezEBS - 450 Mbpsz	m4.xlargez
m4.2xlargez
m4.4xlargez64 GiBzm4.10xlargeZ40z160 GiBzm4.16xlargezEBS - 10000 Mbpsz256 GiBz	m3.mediumzSSD (1 x 4)zm3.largezSSD (1 x 32)z	m3.xlargezSSD (2 x 40)z
m3.2xlargezSSD (2 x 80))zCluster ComputezCluster CPUzCompute Optimizedz
Dense StorageZGPUzGPU ComputezHigh I/OzHigh MemoryzHigh-Memory ClusterzHigh StoragezGeneral Purpose)r)�call�sizesr
r
r�avail_sizes's�������
�����������@�������������������������������Q��	�������
���������#��)��/��5��;��A��G��M�����er�cCs�|dkrtd��t|t�si}d|vr|d}nt�}tjd|tdd�}i}d|d�}tj|t	�t
�tdd	�}|D]}|||d
<q9|S)zI
    Return a dict of all available VM images on the cloud provider.
    r�z`The avail_images function must be called with -f or --function, or with the --list-images option�owner�amazon��default�DescribeImages)�ActionZOwnerr��r*rq�opts�sigver�imageId)rr$�dictr
r�get_cloud_config_valuerrLr�rR�get_provider)�kwargsr�r�rqr�rG�images�imager
r
r�avail_images�s0�

�
�r�cCs4tjj�t�d|t�|ttjj�tjj�t|���S)z-
    Return the script deployment object
    �script)	rr\�cloudZ	os_scriptrr�rZsalt_config_to_yamlZ
minion_config��vm_r
r
rr��s��r�cC�tjd|tdd�S)z
    Return the keyname
    �keynameF��
search_global�rr�rr�r
r
rr��sr�cCr�)z#
    Return the security group
    �
securitygroupFr�r�r�r
r
rr����r�cCr�)aX
    Return the IAM profile.

    The IAM instance profile to associate with the instances.
    This is either the Amazon Resource Name (ARN) of the instance profile
    or the name of the role.

    Type: String

    Default: None

    Required: No

    Example: arn:aws:iam::111111111111:instance-profile/s3access

    Example: s3access

    �iam_profileFr�r�r�r
r
rr��s�r�cCs0tjd|tddd�}|dvrt�d|�d}|S)zj
    Return the ssh_interface type to connect to. Either 'public_ips' (default)
    or 'private_ips'.
    �
ssh_interface�
public_ipsF�r�r�)r��private_ipsziInvalid ssh_interface: %s. Allowed options are ("public_ips", "private_ips"). Defaulting to "public_ips".)rr�rrY�warning)r�r�r
r
rr��s
��r�cCs�tjd|tddd�}t|t�sdSd|i}tjd|tddd�|d<tjd|tddd�|d<tjd|tddd�|d	<tjd
|tddd�|d
<tjd|tddd�|d<|d	}|durftj�|�sftd�	|���|durr|d
srtd
��|S)z/
    Return the ssh_gateway configuration.
    �ssh_gatewayNFr�Zssh_gateway_portZssh_gateway_usernameZssh_gateway_userZssh_gateway_private_keyZssh_gateway_keyZssh_gateway_passwordZssh_gateway_commandz7The defined ssh_gateway_private_key '{}' does not existzYNo authentication method. Please define:  ssh_gateway_password or ssh_gateway_private_key)
rr�rr$�str�osrW�isfilerrX)r�r��ssh_gateway_config�key_filenamer
r
r�get_ssh_gateway_configsB
�


�

�

�

�

����r�c
Cs"t�dtjd|p
t�ttdd��S)z�
    Return the EC2 region to use, in this order:
        - CLI parameter
        - VM parameter
        - Cloud profile setting
    r*Fr�)rrKrr�r
r-r�r
r
rrRCs��rRcCs\|dkrtd��i}ddi}tj|t�t�tdd�}|D]}|d|dd	�||d<q|S)
z&
    List all available locations
    r�zfThe avail_locations function must be called with -f or --function, or with the --list-locations optionr�ZDescribeRegionsr�r�Z
regionNameZregionEndpoint)r'r<)rrLr�rRr�r)r�r�rGr|rvr
r
r�avail_locationsVs$���r�cCsZtjd|tdd�}|durdSt|�}||vrtd�|���||dkr+td�|���|S)z-
    Return the availability zone to use
    Zavailability_zoneFr�Nz?The specified availability zone isn't valid in this region: {}
�	availablez>The specified availability zone isn't currently available: {}
)rr�r�list_availability_zonesrrX)r�ZavzZzonesr
r
r�get_availability_zonets&�����r�cCr�)zq
    Returns the Tenancy to use.

    Can be "dedicated" or "default". Cannot be present for spot instances.
    ZtenancyFr�r�r�r
r
r�get_tenancy�sr�cs�tjd|tdd�}|�d�r|Sttd�sit_n
|tjvr#tj|Sdd|d�}d	d
��ttj	|t
�t�tdd�t�fd
d��d�dd}|tj|<|S)z$
    Returns the ImageId to use
    r�Fr�zami-r�r�r'�r�z
Filter.0.NamezFilter.0.Value.0cSstj�|dd�S)NZcreationDatez%Y-%m-%dT%H:%M:%S.%fZ)rO�strptime)�xr
r
r�_t�szget_imageid.<locals>._tr�r�cstjj��|��|��Sr)rr\�compat�cmp)�i�j�r�r
r�<lambda>�szget_imageid.<locals>.<lambda>)r���r�)
rr�r�
startswith�hasattr�get_imageidr�r^rLr�rRr�r)r�r�rG�image_idr
r�rr��s8



���	�	�

r�cCs�ddi}tj|t�t�tdd�D]:}d|vrJ|�di��dg�}t|t�s(|g}|D]}|ddkrI|d	|krIt�	d
||d�|dSq*qdS)
z5
    Returns the SubnetId of a SubnetName to use
    r��DescribeSubnetsr�r��tagSetr)r�NamerzAWS Subnet ID of %s is %s�subnetIdN)
rLr�rRr�rrKr$r%rYrZ)�
subnetnamerG�subnet�tagsr r
r
r�_get_subnetname_id�s(
�

��rcCs<tjd|tdd�}|r
|Stjd|tdd�}|rt|�SdS)z%
    Returns the SubnetId to use
    �subnetidFr�r�N)rr�rr)r�rr�r
r
r�get_subnetid�s��rcCstt�}t|t�s|g}ddi}tj|t�t�tdd�D]}|d|vr5t�	d|d|d�|�
|d�qt|�S)zC
    Returns the SecurityGroupId of a SecurityGroupName to use
    r��DescribeSecurityGroupsr�r��	groupName� AWS SecurityGroup ID of %s is %s�groupId)�setr$r%rLr�rRr�rrYrZ�add)�securitygroupname_list�securitygroupid_setrG�sgr
r
r�_get_securitygroupname_id�s$

���r
cCs�t�}tjd|tdd�}|r|�t|��}tjd|tdd�}|rSt|t�s(|g}ddi}tj|t	�t
�tdd�D]}|d	|vrRt�d
|d	|d�|�
|d�q8t|�S)z%
    Returns the SecurityGroupId
    �securitygroupidFr��securitygroupnamer�rr�r�rrr)rrr�r�unionr$r%rLr�rRr�rYrZr	)r�rZsecuritygroupid_listr
rGrr
r
rrs6��

���rcCr�)z+
    Returns the PlacementGroup to use
    ZplacementgroupFr�r�r�r
r
r�get_placementgroup(r�rcCr�)zE
    Returns the spot instance configuration for the provided vm
    �spot_configFr�r�r�r
r
r�get_spot_config1r�rcCs>|dur
t�pd}n|�dd�}d|vr|�d�}|d}|S)z+
    Extract the provider name from vm
    Nr	rq�:r)rrKr!)r�rqZ
prov_compsr
r
rr�:s
r�cCsLi}ddt|�d�}tj|t|�t�tdd�}|D]
}|d||d<q|S)z;
    List all availability zones in the current region
    ZDescribeAvailabilityZoneszregion-namer�r�r�Z	zoneStateZzoneName)rRrLr�r�r)r�r�rGr|�zoner
r
rr�Is��r�cCr�)z�
    Return the block device mapping:

    .. code-block:: python

        [{'DeviceName': '/dev/sdb', 'VirtualName': 'ephemeral0'},
          {'DeviceName': '/dev/sdc', 'VirtualName': 'ephemeral1'}]
    �block_device_mappingsTr�r�r�r
r
rrbs	�rcCsVddi}|�dd�|d<tj|dt|�t�tdd�}|D]}d	|vr(|d	Sqd
S)z'
    Request and return Elastic IP
    r�ZAllocateAddress�domainZvpcZDomainTr��rpr*rqr�r�ZallocationIdN)�
setdefaultrLr�rRr�r)�	interfacer�rGZeipsZeipr
r
r�_request_eipps��rcCs�d|vr|ddur|d|dd�Sddi}tj|dt|�t�tdd	�}d
|vr5d|vr5t|d�|d
<d|vrEd
|vrEt|d
�|d<t||�}|sVtd�	|�
d����d|i}dD]}||vrh||||<q\dD]}||vr{|�t|||��qkd|vr�dD]}||vr�||||<q�|�
dd�|d<|Sd|d<tj|dt|�t�tdd	�}|d}|r�|�
d�s�t
d|����|�
d�}t�d||d�|�
dd�}	t|	t�r�t||	|d�|�
d�r�t||�
d�|d�nD|�
d�r�t||�}
t||
|d�n2|�
d��r1t|�}g}t|�D]
\}
}|�t||���qt|�D]\}
}t|||
||d��q!d|v�rWd |d|dd!�}tj|dt|�t�tdd	�}d"|v�rWt�d#�|d|d�S)$z_
    Create an Elastic Interface if necessary and return a Network Interface Specification
    �NetworkInterfaceIdN�DeviceIndex)rrr�r�Tr�r�SecurityGroupIdr�SubnetIdr�zNo such subnet <{}>)�Description�PrivateIpAddressZSecondaryPrivateIpAddressCount)ZPrivateIpAddressesr�AssociatePublicIpAddress)rr"r�delete_interface_on_terminate�DeleteOnTerminationZCreateNetworkInterfacer�networkInterfaceIdzFailed to create interface: z$Created network interface %s inst %sFr�Z
associate_eipZallocate_new_eipZallocate_new_eipsr��
CreateTags)r�zResourceId.0z	Tag.0.KeyzTag.0.Valuer@z#Failed to set name of interface {0})rLr�rRr�rr
r�_get_subnet_id_for_interfacerrXrK�update�_param_from_configrrYrZr$r��_associate_eip_with_interfacer�_list_interface_private_addrsrlr&r@)rr�rG�subnet_query�	subnet_id�kr|�eni_desc�eni_idZassociate_public_ipZ_new_eipZ	addr_listZeip_listr�addrZ
tag_paramsZtag_responser
r
r�_create_eni_if_necessary�s���	�
������	





��

r2cCsp|D]3}d|vr5t|dt�rt|d|�}|dur|Sq|dD]}t||�}|dur4|Sq#qdS)Nr))r$r��_get_subnet_from_subnet_query)r,rZsubnet_query_resultr-r�r
r
rr'�s ��
���r'cCs:d|vr|�d�r|d|dkr|dSdS|dSdS)Nr�r)rK)r,rr
r
rr3s
��r3cCsr|�d�}|s	dS|g}|�di��dg�}t|t�s|S|D]}|�d�dkr)q|�d�r6|�|�d��q|S)z�
    Returns a list of all of the private IP addresses attached to a
    network interface. The 'primary' address will be listed first.
    �privateIpAddressNZprivateIpAddressesSetr)�primary�true)rKr$r%r&)r/r5�	addresses�lst�entryr
r
rr+s


�r+cCszt|t�s	td��d|d�}|��D]\}}|||<qtj|dt|�t�tdd�}t|t�r;|�	d�r;td�
||���|S)	z`
    Change properties of the interface
    with id eni_id to the values in properties dict
    z#ENI properties must be a dictionaryZModifyNetworkInterfaceAttribute)r�rTr�rr@z1Could not change interface <{}> attributes <'{}'>)r$r�rr,rLr�rRr�rrKrX)r0Z
propertiesr�rGr.�vr|r
r
r�_modify_eni_properties's(


�	��r;cCsnd||d�}|r||d<tj|dt|�t�tdd�}|d�d�s)td	�||���t�	d
||�|d�d�S)a�
    Accept the id of a network interface, and the id of an elastic ip
    address, and associate the two of them, such that traffic sent to the
    elastic ip address will be forwarded (NATted) to this network interface.

    Optionally specify the private (10.x.x.x) IP address that traffic should
    be NATted to - useful if you have multiple IP addresses assigned to an
    interface.
    ZAssociateAddress)r�rZAllocationIdr!Tr�r�Z
associationIdzGCould not associate elastic ip address <{}> with network interface <{}>z1Associated ElasticIP address %s with interface %s)
rLr�rRr�rrKrrXrYrZ)r0Zeip_idZ
private_ipr�rGr|r
r
rr*Fs*��	�r*cCsFi}g}|D]}d|vr"|d|vrt�d�dS||t|d�<q|ddddd}t|t�rE|D]
}|�|d|df�q6n|�|d|df�|D]N\}}	d	}
d
||	dvri||	dd
}
nd||	dvry||	dd}
|	d
|
d�}t|||d�}d||	dvr�d||	ddi}
t||
|d�}qRdS)Nrz5Duplicate DeviceIndex in profile. Cannot update ENIs.r�instancesSetr)ZnetworkInterfaceSetr%�
attachmentTr$ZdeviceIndexr#ZattachmentId)zAttachment.AttachmentIdzAttachment.DeleteOnTerminationr�ZSourceDestCheckzSourceDestCheck.Value)rYr@r�r$r%r&r;)Z
interfaces�instancer�Zconfig_enisZ
instance_enisrZ
query_enisZ	query_enir0Zeni_dataZdelete_on_terminateZparams_attachmentZset_eni_attachment_attributesZparams_sourcedestZset_eni_sourcedest_propertyr
r
r�_update_enismsZ
�
���
�
�������r@cCs�i}t|t�r|��D]\}}|�t|�d|��|��q|St|t�s)t|t�rCt|�D]\}}|�d|��}|�t||��q-|St|t�rU|�|t	|��
�i�|S|�||i�|S)aW
    Return EC2 API parameters based on the given config data.

    Examples:
    1. List of dictionaries
    >>> data = [
    ...     {'DeviceIndex': 0, 'SubnetId': 'subid0',
    ...      'AssociatePublicIpAddress': True},
    ...     {'DeviceIndex': 1,
    ...      'SubnetId': 'subid1',
    ...      'PrivateIpAddress': '192.168.1.128'}
    ... ]
    >>> _param_from_config('NetworkInterface', data)
    ... {'NetworkInterface.0.SubnetId': 'subid0',
    ...  'NetworkInterface.0.DeviceIndex': 0,
    ...  'NetworkInterface.1.SubnetId': 'subid1',
    ...  'NetworkInterface.1.PrivateIpAddress': '192.168.1.128',
    ...  'NetworkInterface.0.AssociatePublicIpAddress': 'true',
    ...  'NetworkInterface.1.DeviceIndex': 1}

    2. List of nested dictionaries
    >>> data = [
    ...     {'DeviceName': '/dev/sdf',
    ...      'Ebs': {
    ...      'SnapshotId': 'dummy0',
    ...      'VolumeSize': 200,
    ...      'VolumeType': 'standard'}},
    ...     {'DeviceName': '/dev/sdg',
    ...      'Ebs': {
    ...          'SnapshotId': 'dummy1',
    ...          'VolumeSize': 100,
    ...          'VolumeType': 'standard'}}
    ... ]
    >>> _param_from_config('BlockDeviceMapping', data)
    ... {'BlockDeviceMapping.0.Ebs.VolumeType': 'standard',
    ...  'BlockDeviceMapping.1.Ebs.SnapshotId': 'dummy1',
    ...  'BlockDeviceMapping.0.Ebs.VolumeSize': 200,
    ...  'BlockDeviceMapping.0.Ebs.SnapshotId': 'dummy0',
    ...  'BlockDeviceMapping.1.Ebs.VolumeType': 'standard',
    ...  'BlockDeviceMapping.1.DeviceName': '/dev/sdg',
    ...  'BlockDeviceMapping.1.Ebs.VolumeSize': 100,
    ...  'BlockDeviceMapping.0.DeviceName': '/dev/sdf'}

    3. Dictionary of dictionaries
    >>> data = { 'Arn': 'dummyarn', 'Name': 'Tester' }
    >>> _param_from_config('IamInstanceProfile', data)
    {'IamInstanceProfile.Arn': 'dummyarn', 'IamInstanceProfile.Name': 'Tester'}

    r=)r$r�r,r(r)r%�tuplerl�boolr��lower)rr+�paramr.r:rZ	conf_item�prefixr
r
rr)�s3
�	
��r)c0s�|dkrtd��|�dt|��}t|�}|dur9d|vr%td�|d���dd	d
|vr/|d
nd|dd�}d
}ntjd|tddd�}tjd|tddd�}d||d�}d}t|�}|||d<d}	tjd|tddd�}
|
durztjd|tddd�}	n-t	�
d|
�tj�
|
�r�tjj�|
d��}tjj�|���}	Wd�n1s�wYtjj�t||	�}	|	dur�zt�tjj�|	��||d<Wnty�}zt	�d|�WYd}~nd}~wwtjd|tdd�}
|
||d<t|�}|r�|||d <t|�}|�rt|t��s|||d!<nt |�D]\}}|||d"|��<�qt!|�}|�rHz|�"d#��r4|||d$<n|||d%<Wnt#�yGt$d&��wt%|�}|du�rW|||d'<t&|�}|du�rr|du�rnt$d(�|d���||d)<t'|�}|du�r�|||d*<t(|�}|�r�t|t��s�|||d+<nt |�D]\}}|||d,|��<�q�t)|�}|du�r�|||d-<t*|�}|�r�|D]
}d.|v�r�|�+d.��q�|}|�r�|�,t-|d/|��tjd0|tdd�}|�rg}|D]}t	�.d1|�t/||�}|�0|��q�|�,t-|d2|��tjd3|tdd�}|du�r)t|t1��s#t$d4��|||d5<tjd6|tdd�} tjd7|tdd�}!|!du�rTt|!t1��sJt$d8��|�,t-|d9|!��| �rat| t1��sat$d:��| |d;<| �rIt	�2d<||d�d=|d>�}"zt3j4|"t|�t5�td?d@�}#dA|#v�r�|#dAWSt	�.dB|#�Wnt�y�}zt	j6dC||d|t7j8dD��d}~ww|#�s�dE�|�}$t|$��d}%d}&dF|#dGv�r�|#dGdFdu�r�|#dGdFdH}'t|'t��r�|'dG}'|'dI}%|'dJ�dKd�}&t	�2dL|%�|%du�rI|�rdMdN�|D�}(ng}(|%|(v�r|(�9|%�})nt:|(�})|%||�dO|)�dP�<dQ�||)�}*t;| ��<�||*<|�rI|)t:|�k�rIdR||)v�rIdS�||)�}+|&||+<tjdT|tddd�},|,�r`t|,t1��s`t$dU��t=dVdWdXdY�|d�t=dZd[|t|��|d\�td]td^d_�t5|��zt3j4|d`|�td?d@�}-dA|-v�r�|-dAWSWnt�y�}z
t	j6da|d|t7j8dD��d}~ww|�rX|-dGdb}.|.|dc<�fddde�}/t=dVdWdfdg�|d�td]td^dh�z3t>|/|.|ftjdi|tdjdk�tjdl|tdmdk�tjdn|tddk�tjdo|tdpdk�dq�}-t	�.dr|-�W|-|fSt?t@f�yW}z8z1zds|.dt�}t3j4||�td?d@�}-t	�.du|.|-�Wn
t�y>YnwWtt;|���Wtt;|���tt;|���d}~ww|-|fS)vz�
    Put together all of the information necessary to request an instance on EC2,
    and then fire off the request the instance.

    Returns data about the instance
    �functionz?The request_instance action must be called with -a or --action.r*NZ
spot_pricez<Spot instance config for {} requires a spot_price attribute.r'ZRequestSpotInstancesr��typezone-time)r�Z
InstanceCountZTypeZ	SpotPricezLaunchSpecification.�min_instanceFr�r�r��max_instanceZRunInstances)r�ZMinCountZMaxCountr?ZImageId�
userdata_file�userdatazuserdata_file: %s�rZUserDatazFailed to encode userdata: %s�sizer�ZInstanceType�KeyNamezSecurityGroup.1zSecurityGroup.zarn:aws:iam:zIamInstanceProfile.ArnzIamInstanceProfile.Namez''iam_profile' should be a string value.zPlacement.AvailabilityZonez@Spot instance config for {} does not support specifying tenancy.zPlacement.TenancyrzSecurityGroupId.1zSecurityGroupId.zPlacement.GroupNamer �BlockDeviceMapping�network_interfaceszCreate network interface: %sZNetworkInterfaceZ
ebs_optimizedz*'ebs_optimized' should be a boolean value.ZEbsOptimizedZdel_root_vol_on_destroyZtermination_protectionz3'termination_protection' should be a boolean value.ZDisableApiTerminationz4'del_root_vol_on_destroy' should be a boolean value.�set_del_root_vol_on_destroyz?Attempting to look up root device name for image id %s on VM %sr�)r��	ImageId.1r�r�r@zEC2 Response: '%s'z=Error getting root device name for image id %s for VM %s: 
%s)Zexc_info_on_loglevelzSThere was an error querying EC2 for the root device of image id {}. Empty response.�blockDeviceMappingrr)�
deviceName�ebsZ
volumeTypezFound root device name: %scSsg|]}|d�qS)�
DeviceNamer
)�.0�devr
r
r�
<listcomp>�sz$request_instance.<locals>.<listcomp>�BlockDeviceMapping.�.DeviceNamez/{}BlockDeviceMapping.{}.Ebs.DeleteOnTerminationzEbs.VolumeTypez&{}BlockDeviceMapping.{}.Ebs.VolumeType�del_all_vols_on_destroyz4'del_all_vols_on_destroy' should be a boolean value.�cloud.fire_event�eventzrequesting instancezsalt/cloud/{}/requesting�cloud.filter_eventZ
requesting)r�r*�sock_dir�	transport��argsrarbr=zGError creating %s on EC2 when trying to run the initial deployment: 
%s�spotInstanceRequestId�
spotRequestIdcs�d|d�}tj||�tdd�}|st�d�dSt|t�r+d|vr+t�d|d�dSt�d	|�|d
�	d�}|dkr>|S|d
krPt�
d|d
dd�dS|dvr[t�d�dSdS)NZDescribeSpotInstanceRequests�r�zSpotInstanceRequestId.1r�r��5There was an error while querying EC2. Empty responseFr@�#There was an error in the query. %s�Returned query data: %sr�stateZactive�openzSpot instance status: %s�status�message)Z	cancelledZfailed�closedzKSpot instance request resulted in state '{0}'. Nothing else we can do here.)rLr�rrYr@r$r�r�rZrKr�)�sir_idr*rGr+rk�rqr
r�__query_spot_instance_requestIs2�
�
��z7request_instance.<locals>.__query_spot_instance_requestzwaiting for spot instancezsalt/cloud/{}/waiting_for_spot)rarbZwait_for_spot_timeoutr�r�Zwait_for_spot_intervalr�Z!wait_for_spot_interval_multiplierZwait_for_spot_max_failuresr�)r�rHr�r�r�zwait_for_spot_instance data %s�CancelSpotInstanceRequestsrgz4Canceled spot instance request %s. Data returned: %s)ArrKrRrrXrr�rr�rYrdr�rW�existsrr\�files�fopen�stringutils�
to_unicode�readr�Zuserdata_template�base64�	b64encode�to_bytes�	Exception�	exceptionr�r�r$r%rlr�r�rrr�r�rrrr�popr(r)rZr2r&rBr�rLr�r�r@�logging�DEBUG�indexrr�rC�	__utils__r�rr)0r�r�r*rrGZspot_prefixrHrJr�rLrK�fh_r}Zvm_sizeZ
ex_keynameZex_securitygroupZcounterZsg_Zex_iam_profileZaz_Ztenancy_Z	subnetid_Zex_securitygroupidZplacementgroup_�blockdevicemappings_holder�_bdZex_blockdevicemappingsrQZeni_devicesrZ_new_eniZset_ebs_optimizedrRZset_termination_protectionZ	rd_paramsZrd_data�err_msgZrd_nameZrd_typer)Zdev_listZ	dev_indexZtermination_keyZtype_keyZset_del_all_vols_on_destroyr+rprrr
rqr�request_instance�s|����


�
��
�
�������



�



����
�
��
������
�

����

����
���
����

����&������������	���r�c	s"|dkrtd���d}��dt����tdddd��d	�d|itd
tdd�t�d
|�d|d�}t���d}|t	j
kr�t	j|��tddd�\}}t�d|�t|t
�rgd|vrgt�d||d�nt|t�ru|sut�d|�nnt	�|�|d7}q<td�|d������fdd�}z%tjjj|||ftjd�tdd�tjd�td d�tjd!�tdd�d"�}Wn5ttfy�}z'z zt�d	�Wn	ty�YnwWtt|���Wtt|���tt|���d#}~wwd$�v�r�d$du�rtddd%d&��d	�d'|itd
tdd�|S)(z:
    Query an instance upon creation from the EC2 API
    rFz=The query_instance action must be called with -a or --action.�instance_idr*r^r_zquerying instancezsalt/cloud/{}/queryingr'rarbrczThe new VM instance_id is %s�DescribeInstances�r��InstanceId.1rTr�)r*rqr�ror�zThe query returned: %sr@z:There was an error in the query. %s attempts remaining: %sz4Query returned an empty list. %s attempts remaining.rz'An error occurred while creating VM: {}cs�tj|��tdd�}|st�d�dSt|t�r&d|vr&t�d|d�dSt�d|�t	��dkrCd	|d
ddvr>|St�d
�t	��dkr\d|d
ddvrU|St�d�dSdS)Nr�r�rhFr@rirjr��	ipAddressrr=r)zPublic IP not detected.r�r4zPrivate IP not detected.)
rLr�rrYr@r$r�r�rZr�)rG�urlr+�r*rqr�r
r�__query_ip_address�s&
�

�z*query_instance.<locals>.__query_ip_address�wait_for_ip_timeoutr�r��wait_for_ip_intervalr��wait_for_ip_interval_multiplier�r�rHr�r�N�reactorzinstance queriedzsalt/cloud/{}/query_reactorr+)rrKrRr�rXrrYrZr�rLrMr�r$r�r�r%rkrr\r��wait_for_iprr�rr�destroyr�)	r�r�r�rGrsr+rnr�r}r
r�r�query_instance�s���	


���
����
�
�����	�	r�cCs8|dkrtd��|duri}|duri}|�dt|��}tdddd�|d	�d
|itdtdd
�t�d|td�}t�d|td�}t�d|t��rtjd|tdd�}tjd|tdd�}	tjd|tdd�}
tjd|tdd�}tjd|tdd�}tjd|tdd�}
|	r�|	d kr�t�	d!�	t
|d	d"|d#id$d%�}|�d&d�}	|	dur�t�	|�t�d'�n|}d(|d&<d(|d)<t�	|�|	|d<nq�t
jjj|d*|d+�s�td,��|s�t�	d-�t
jjj|||	|
|d.�s�td/���ntjd0|td1d�}t
jjj|||d+��std2��t�	d3�t
jjj||||	||
d4��std5��n�t
jjj||||d6��r�tjd7|tdd�}|�r�i}d8|v�rTt|d9d$t|�d:�}t�|�t�d;�d8|v�s:t
jj�|d8�}|�d<�}t|�d=k�rkdS|d�d>�}d}|d?��D]}|�s��qz|d@|�dA|��7}�qzt
jj�|dB��}|�t
jj�|��Wd�n	1�s�wY|��|dCD]5}t
jjj |||tjdD|td'd�|dE||tjdF|tdGd�tjd7|tdHd�dI�	�r�|tdJ<||dJ<n�q�tdK��ntdL��dM|v�r|dMdu�rtdddNdO�|d	�d
|itdtdd
�|S)PzR
    Wait for an instance upon creation from the EC2 API, to become available
    rFz@The wait_for_instance action must be called with -a or --action.N�gatewayr^r_zwaiting for sshzsalt/cloud/{}/waiting_for_sshr'�
ip_addressrarbrc�ssh_connect_timeouti��ssh_port�Z
win_installerZwin_usernameZ
Administratorr��win_passwordr?�win_deploy_auth_retriesr��win_deploy_auth_retry_delayr�	use_winrmF�winrm_verify_sslT�autoz/Waiting for auto-generated Windows EC2 password�key_file�private_keyr��r'r�r��passwordr�zXXX-REDACTED-XXX�passwordDatai�)�portrHz(Failed to connect to remote windows hostz+Trying to authenticate via SMB using psexec)ZretriesZretry_delayz8Failed to authenticate against remote windows host (smb)�
winrm_portibz0Failed to connect to remote windows host (winrm)z.Trying to authenticate via Winrm using pywinrm)rHZverifyz2Failed to authenticate against remote windows host)r�rHr��known_hosts_file�output_decodedr��r�r�r*�z!-----BEGIN SSH HOST KEY KEYS-----r<z-----END SSH HOST KEY KEYS-----rrArD�a�	usernamesZwait_for_passwd_timeoutr�Zwait_for_passwd_maxtries�z	/dev/null)	rwr��usernameZssh_timeoutr��display_ssh_outputr�Zmaxtriesr�Zssh_usernamez)Failed to authenticate against remote sshzFailed to connect to remote sshr�zssh is availablezsalt/cloud/{}/ssh_ready_reactor)!rrKr�r�rXrrr�rYrZ�get_password_datar�r�rr\r�Z
wait_for_portZvalidate_windows_credZwait_for_winrm�get_console_outputrR�pprintrwrxr!r�
splitlinesrurv�writeZto_str�closeZwait_for_passwd)r�r+r�r�r�r�r�r�r�Z
win_passwdr�r�r�r�Z
password_dataZlogging_datar�r�Zconsole�outputr(ry�lineZfp_�userr
r
r�wait_for_instance$	sN
��	�������

�

��
������
�����
�


�
��������	r�cCsX|durtd��tj�|�std|�d���t�t�|�j�}|dvr*td�|���dS)NzRThe required 'private_key' configuration setting is missing from the 'ec2' driver.zThe EC2 key file 'z' does not exist.
)�i�z<The EC2 key file '{}' needs to be set to mode 0400 or 0600.
T)rr�rWrt�stat�S_IMODE�st_moderX)r�Zkey_moder
r
r�_validate_key_path_and_mode�	s �
���r�c$
Cs|rtd��z|drtjtt�pd|d|d�durWdSWn	ty(Ynwtjd|tdd�}tjd	|td
d�}tjd|tddd
�}|rKt|�tdddd�	|d�tdd|gd��tdtdd�td|d|dd|d�||d<||d<t
|�|d<t|�}||d<t�
d|d|�tjjj|tdd �|d!<d"|vr�d#|vr�d$|vr�t�d%|d�tjj�tj�d&|t��\|d$<|d#<nCt|�dur�td'��t||�\}}t|t�r�t�d(|�iSg|d)<|D]}|d)�|d*�q�|d)��|d"<|d)�r
t|d)�t|�}tjd+|tidd,�}t|t��s%td-��|��D]
}	t|	t��s5td.���q)|d|d/<tddd0d1�	|d�d2|itdtdd�tjjj t!d3|d||d"d4|d5�d6|v�r�d+|d6v�r�t|d6d+t��s�td-��|d6d+��D]
}	t|	t��s�td.���q�i}
d7|v�r�td8��|d7}|d|
d/<|d6d+�"�D]	\}}
|
|
|<�q�tddd0d9|�d:�d2|
itdtdd�tjjj t!d3|d|
|d4|d5�tjd;|tdd,�}|�r�t#|||�t�
d<|d�|d=d>d?}t$|�d@k�r|dA}t�
dB|�n
|dC}t�
dD|�||dE<tjj�%|t�d@k�r;|dA}t�
dF|�n
|dC}t�dF|�||dG<|�r\tjdH|tdd�}t&||||�}|�'�}tjdI|tdd,�}|�r�tdddJdK�	|d�dI|itdtdd�t�
dL|d�t(|d||dMdN|d*|�)dOd�dP�d4dQ�}||dR<tjdS|tddd,�}|�r�t�dT|�t*|ddS|i|d"d4dU�}t|t��r�|�)dVd��r�t�dW|d"|�iStdX|t��"�D]\}}	|�+||	��q�t�
dY|d�t�dZ|dt,�-|��|d|d|d|d"d[�}|�r||dI<|�r&||dS<tddd\d]�	|d�tdd^|t.|��tdtdd�t/|d"d_�}td`|t�t�|�0|�i}t1|�}|�rt|D]}d+|v�rr|d+||da<�qci}|�r�|db�"�D]S\}}g} t|t��r�| �|�n|D]}!| �|!��q�| D]2}"|"dc|v�r�d/||"dcv�r�|d||"dcd/<|"dc|v�r�||"dc||"|ddde<�q��q|�r|�"�D],\}#}tddd0dft|#��d:�d2|itdtdd�tdgt!d3|d||#d4|dh��q�|S)iz-
    Create a single VM from a data dict
    z,You cannot create an instance with -a or -f.�profiler	r�F�deployTr�r�r?r�NrIr^r_zstarting createzsalt/cloud/{}/creatingr'r`Zcreating)r'r�rq�driverrarbrczcloud.cachedir_index_addr�r�r�r*zCreating Cloud VM %s in %s)zec2-userZcentosZubuntuZadminZbitnamir~)Z
default_usersr�r�Zpub_keyZpriv_keyzGenerating minion keys for '%s'ZkeysizezNThe required 'keyname' configuration setting is missing from the 'ec2' driver.zError requesting instance: %sZinstance_id_list�
instanceIdr r�z'tag' should be a dict.zR'tag' values must be strings. Try quoting the values. e.g. "2013-09-19T20:09:46Z".r�zsetting tagszsalt/cloud/{}/taggingrr�r�)rHr'rr�r�r*rrfzFailed to find spotRequestIdzsalt/cloud/spot_request_z/taggingrQzCreated node %srr=r)r�r4zSalt node data. Private_ip: %sr�zSalt node data. Public_ip: %sZssh_hostzSalt interface set to: %sZ	salt_hostr��volumeszattaching volumeszsalt/cloud/{}/attaching_volumesz$Create and attach volumes to node %sZ	placementZavailabilityZoner])r�rr�r]�r�zAttached Volumes�ssm_documentz!Associating with ssm document: %s�r�r�r@z4Failed to associate instance %s with ssm document %szcloud.bootstrapzCreated Cloud VM '%s'z'%s' VM creation details:
%s)r'r�rqr�zcreated instancezsalt/cloud/{}/created�created�r��cloud.cache_noderWrTrUZrootDeviceType�volumeIdzsalt/cloud/block_volume_zcloud.wait_for_fun)rHr'r�resource_idr�r*)2rrZis_profile_configuredrrrr�r�r�rXr�rRrYr�rr\r�Z
ssh_usernamesrZZgen_keysr�r�r$r�r@r&r�queue_instancesr�r�rrzZwait_for_fun�set_tagsr,r@r�Zget_salt_interfacer�rN�create_attach_volumesrK�ssm_create_associationrr�Zpformatr%�	_get_noder(r)$r�r�r�r�r�r*r+r?rrZspot_request_tagsrpr.r:rQr�Zsalt_ip_addressr�r�r�r�r�ZassocrZ
event_data�nodeZex_blockdevicetagsr�r�Zblock_device_volume_id_mapZ_device�_mapZbd_itemsZmapitemZ	blockitemZvolidr
r
r�create
s������
�
��
�
�
���

���	���

��
����	

��

�����


�
�����	
�
r�cCs*|D]}t|d�}td|t�t�qdS)a�
    Queue a set of instances to be provisioned later. Expects a list.

    Currently this only queries node data, and then places it in the cloud
    cache (if configured). If the salt-cloud-reactor is being used, these
    instances will be automatically provisioned using that.

    For more information about the salt-cloud-reactor, see:

    https://github.com/saltstack-formulas/salt-cloud-reactor
    r�r�N)r�r�rr)�	instancesr�r�r
r
rr��s
�r�cCs�|dkrtd��d|vrt|�d|d<t|dt�r%tjj�|d�}n|d}g}|D]�}d}d�|d|�}||d	d
�}	d|vrK|d|	d<nd|vrV|d|	d<nd
|vra|d
|	d
<nt	d��d|vro|d|	d<d|vry|d|	d<d|vr�|d|	d<d|vr�|d|	d<d|vr�|d|	d<d|	vr�t
|	d|d�}
d}d|
vr�|
d|	d<t||	d|dd�|ddd�}|�dd�}|r�|r�|dur�t
|d|d|d�|r�d�|	d|d||d�}
t�|
�|�|
�q-|S)z3
    Create and attach volumes to created node
    r�zDThe create_attach_volumes action must be called with -a or --action.r�r�r�Fz{} on {}�devicer)�volume_namer�	volume_id�snapshotrNzNCannot create volume.  Please define one of 'volume_id', 'snapshot', or 'size'rrG�iops�	encrypted�kmskeyidrF)r��wait_to_finishTr�)r�r�r�r]N)r�r�rz'{} attached to {} (aka {}) as device {})rr�r$r�rr\�yaml�	safe_loadrXr�
create_volume�
attach_volumerK�_toggle_delvolrYr�r&)r'r�r�r�r�r�Zvolumer�r�Zvolume_dictZcreated_volume�attachZdelvols_on_destroyr9r
r
rr��sz������

�r�cC�||dkrtd��t�d|�t|�d}tdddd|�d	�||d
�tdtdd
�d|d�}tj|t�t	�tdd�}|S)z
    Stop a node
    r�z3The stop action must be called with -a or --action.zStopping node %sr�r^r_zstopping instance�salt/cloud/z	/stopping�r'r�rarbrcZ
StopInstancesr�r�r��
rrYr�r�r�rrLr�rRr��r'r�r�rGr|r
r
r�stop�s*
�
	�r�cCr�)z
    Start a node
    r�z4The start action must be called with -a or --action.zStarting node %sr�r^r_zstarting instancer�z	/startingr�rarbrcZStartInstancesr�r�r�r�r�r
r
r�starts.�
�
	�r�c	Cs�|duri}|dur
t�}|dur;d|vr|d}|d=d|vr'|d}|d=|dur9|dur8t|d|d�d}n|}|durCddiSd|d	�}t�d
||�|rU|sU|}t|���D]\}\}	}
|	|d|�d�<|
|d|�d
�<q[d}|tjkr�tj|d|t	�t
dd�t|d|d�}t�d|�d}
|D]>}|d|vr�q�|�d�dur�|�|d�dkr�q�t
|�|d��t
|d�kr�t�d|d|�|d�|d�d}
nq�|
r�t�d|�|d7}t�|�qt|Std|�d���)aw
    Set tags for a resource. Normally a VM name or instance_id is passed in,
    but a resource_id may be passed instead. If both are passed in, the
    instance_id will be used.

    CLI Examples:

    .. code-block:: bash

        salt-cloud -a set_tags mymachine tag1=somestuff tag2='Other stuff'
        salt-cloud -a set_tags resource_id=vol-3267ab32 tag=somestuff
    Nr�r��r'r�r*r�rJz5A valid instance_id or resource_id was not specified.r&�r�zResourceId.1zTags to set for %s: %s�Tag.�.Keyz.Valuerr�r��rmr*rqr�r�r�r�zSetting the tags returned: %sFrrr?z,Setting the tag %s returned %s instead of %sTz)Failed to set tags. Remaining attempts %srzFailed to set tags on �!)rRr�rYrZrlr,rLrMr�r�r�get_tagsrKr�r�rkr)r'rr�r*r�r�r�rGrZtag_kZtag_vrsZsettagsZfailed_to_set_tagsr r
r
rr�#s|��

�	 ��
r�cCs||durt�}|dur,|dur*|rt|�d}nd|vr!|d}nd|vr)|d}n|}dd|d�}tj|d|t�td	d
�S)aL
    Retrieve tags for a resource. Normally a VM name or instance_id is passed
    in, but a resource_id may be passed instead. If both are passed in, the
    instance_id will be used.

    CLI Examples:

    .. code-block:: bash

        salt-cloud -a get_tags mymachine
        salt-cloud -a get_tags resource_id=vol-3267ab32
    Nr�r�r�ZDescribeTagszresource-id)r��
Filter.1.NamezFilter.1.Valuer�r�r�)rRr�rLr�r�r)r'r�r�r*r�r�rGr
r
rr��s0
���r�cCs�|duri}d|vrtd��|sd|vr|d}|d=|s#t|�d}d|d�}t|d�d��D]\}}||d	|�d
�<q1tj|dt�t�tdd
�|rRt	|d�St	|d�S)a�
    Delete tags for a resource. Normally a VM name or instance_id is passed in,
    but a resource_id may be passed instead. If both are passed in, the
    instance_id will be used.

    CLI Examples:

    .. code-block:: bash

        salt-cloud -a del_tags mymachine tags=mytag,
        salt-cloud -a del_tags mymachine tags=tag1,tag2,tag3
        salt-cloud -a del_tags resource_id=vol-3267ab32 tags=tag1,tag2,tag3
    Nrz7A tag or tags must be specified using tags=list,of,tagsr�r�Z
DeleteTagsr��,r�r�r�r�r�)r�r�)
rr�rlr!rLr�rRr�rr�)r'r�r�r�r�rGrr r
r
r�del_tags�s2�
�	

r�cCsV|dkrtd��t�d||d�t|d|didd�tjj�td||d�dS)	z�
    Properly rename a node. Pass in the new name as "new name".

    CLI Example:

    .. code-block:: bash

        salt-cloud -a rename mymachine newname=yourmachine
    r�z5The rename action must be called with -a or --action.zRenaming %s to %s�newnamer�r�Zpki_dirN)	rrYr�r�rr\r�Z
rename_keyrr�r
r
r�rename�s
�r�c
Cs�|dkrtd��t|�}|d}|�d�}t||ddd�}tdd	d
d|�d�||d
�tdtdd�|dkr?td�|���i}tjdt	�tdd�}|durl|�dt
��j��}t
|d|idd�t�d|�||d<d|d�}	t�}
t�}tj|	|
|tdd�}t�|�|�|d�|dur�d |d!�}	tj|	|
|tdd�}|d|d"<tdd	d#d|�d$�||d
�tdtdd�td%|�t�d&d�dur�td'|t��d(�dt�|S))z�
    Destroy a node. Will check termination protection and warn if enabled.

    CLI Example:

    .. code-block:: bash

        salt-cloud --destroy mymachine
    rFzEThe destroy action must be called with -d, --destroy, -a or --action.r�rer�T)r'r�r��quietr^r_zdestroying instancer�z/destroyingr�rarbrcr6z�This instance has been protected from being destroyed. Use the following command to disable protection:

salt-cloud -a disable_term_protect {}�rename_on_destroyFr�z-DELr��r�r�z>Machine will be identified as %s until it has been cleaned up.ZTerminateInstancesr�r�r�rNrsrgZspotInstancezdestroyed instancez
/destroyedzcloud.cachedir_index_delZupdate_cachedirzcloud.delete_minion_cachedirr)rr�rK�show_term_protectr�rrXrr�r
�uuidZuuid4�hexr�rYr�rRr�rLr�r(rr!)
r'r�Z
node_metadatar�rpZ	protectedr�r�r�rGr*rqr|r
r
rr�
s�
�
�
�	�
��

�
�
�
�	�r�cCsJt|�d}d|d�}tj|dt�t�tdd�}|gkr!t�d�ddiS)	zl
    Reboot a node.

    CLI Example:

    .. code-block:: bash

        salt-cloud -a reboot mymachine
    r�ZRebootInstancesr�r�r�r�ZCompleteZReboot)r�rLr�rRr�rrYr�r�r
r
r�rebootc
s

�	
rcCsF|dkrtd��|ddd�}tj|dt�t�tdd�}t�|�|S)	z5
    Show the details from EC2 concerning an AMI
    rFz;The show_image action must be called with -f or --function.r�r�)rSr�r�r�r�)rrLr�rRr�rrYr�)r�r�rGr|r
r
r�
show_image
s��
rcCsf|s
|dkr
td��|dkr|�dd�}|�dd�}|s"|s"td��t||d�}td	|t�t�|S)
a�
    Show the details from EC2 concerning an AMI.

    Can be called as an action (which requires a name):

    .. code-block:: bash

        salt-cloud -a show_instance myinstance

    ...or as a function (which requires either a name or instance_id):

    .. code-block:: bash

        salt-cloud -f show_instance my-ec2 name=myinstance
        salt-cloud -f show_instance my-ec2 instance_id=i-d34db33f
    r�z)The show_instance action requires a name.rFr'Nr�zCThe show_instance function requires either a name or an instance_idr�r�)rrKr�r�rr)r'r�r�r�r�r
r
r�
show_instance�
s�rcCs�|durt�}ddi}t|��d�r t|�dkst|�dkr |}|r'||d<nd|d<||d	<t�|�t�}d
}|tjkrvztj	|||t
dd�}t|���}t
t|��WStyp|d
7}t�d|pf||�t�|�Ynw|tjks>iS)Nr�r��i-r��r�ztag:Namer�zFilter.1.Value.1rr�r�rz<Failed to get the data for node '%s'. Remaining attempts: %s)rRr�r�rrYrdr�rLrMr�r�_extract_instance_inforz�next�iter�
IndexErrorrZrk)r'r�r*rGrqrsr�Z
instance_infor
r
rr��
s<&



���
�r�cCs|dkrtd��t|p
t��S)�;
    Return a list of the VMs that are on the provider
    r�zBThe list_nodes_full function must be called with -f or --function.)r�_list_nodes_fullrR)r*r�r
r
r�list_nodes_full�
s
�rcCspd|vr4|ddur4|d}t|dt�r,|dD]}|ddkr'|dSq|dS|dddS|dS)Nr�r)rr�rr�)r$r%)r)Ztagsetr r
r
r�_extract_name_tag�
s�rcCsi}|D]y}t|ddt�rH|ddD]1}t|�}|||<|||d<||�t|d|d|d|dd|�dg�|�d	g�d
��qq|dd}t|�}|||<|||d<||�t|d|d|d|dd|�dg�|�d	g�d
��q|S)zE
    Given an instance query, return a dict of all instance data
    r=r)r'r�r�ZinstanceType�
instanceStater4r�)rr�rNrkr�r�)r$r%rr(r�rK)r�r�r?r)r'r
r
rr�
sB


���


��rcCs�t�pd}d|vr|�d�}|d}ddi}tj|||tdd�}d|vr3td	�|dd
dd���t|�}td
||t�|S)z8
    Return a list of the VMs that in this location
    r	rrr�r�r�r�r@�)An error occurred while listing nodes: {}rIrJ�Messagezcloud.cache_node_list)	rr!rLr�rrrXrr�)r*rqr(rGr�r�r
r
rr
s"


���r
cCs�|dkrtd��i}ddi}tj|t�t�tdd�}d|vr-td�|dd	d
d���|D]3}t|dd
t�rA|dd
}n|dd
g}|D]}|dd}t	|�}	|d}
||
d�||	<qJq/|S)z�
    Return a list of the VMs that are on the provider. Only a list of VM names,
    and their state, is returned. This is the minimum amount of information
    needed to check for existing VMs.
    r�zAThe list_nodes_min function must be called with -f or --function.r�r�r�r�r@rrIrJrr=r)r
r'r�)rkr)
rrLr�rRr�rrXr$r%r)r*r�r�rGr�r?r,r)rkr'rr
r
r�list_nodes_min9s<�����rc	Cs�|dkrtd��i}tt��}d|vr"td�|dddd���|D]*}||d||d	||d
||d||d||d
||dd�||<q$|S)r	r�z=The list_nodes function must be called with -f or --function.r@rrIrJrrr�r'rNrkr�r�)rr�r'rNrkr�r�)rrrRrX)r�r�Znodesr�r
r
r�
list_nodesbs,�
��






�	rcCstjj�tt��td|�S)zO
    Return a list of the VMs that are on the provider, with select fields
    zquery.selection)rr\r��list_nodes_selectrrRrr�r
r
rr�s
�rcCs�|dkrtd��|st|�d}d|dd�}tj|t�t�dtdd	�}d
}|D]}d|vr3|d}nq't�|dur=tj	ntj
d|d
krFdpGd|�|S)zZ
    Show the details from EC2 concerning an instance's termination protection state

    r�z@The show_term_protect action must be called with -a or --action.r�ZDescribeInstanceAttributeZdisableApiTermination)r��
InstanceIdZ	AttributeTr��r*rqrpr�r�Frz#Termination Protection is %s for %sr6�enabled�disabled)rr�rLr�rRr�rrYr�r��INFO)r'r�r�r�rGr|Zdisable_protectr)r
r
rr��s>���	��r�cCs�|dkrtd��t�}t|��d�r t|�dkst|�dkr |}|s(|s(td��t|||d�}t�|dur8tjntj	d	|d
|�|d
S)zM
    Show the details from EC2 regarding cloudwatch detailed monitoring.
    r�zGThe show_detailed_monitoring action must be called with -a or --action.rr�rzOThe show_detailed_monitoring action must be provided with a name or instance IDr�Tz Detailed Monitoring is %s for %sZ
monitoring)
rrRr�r�rr�rYr�r�r)r'r�r�r�r*Zmatchedr
r
r�show_detailed_monitoring�s&�&��rcCs@t|�d}d||d�}tj|t�t�dtdd�}t||dd�S)	z=
    Enable or Disable termination protection on a node

    r��ModifyInstanceAttribute)r�rzDisableApiTermination.ValueTr�rr��r'r�r�)r�rLr�rRr�rr�)r'rr�rGr|r
r
r�_toggle_term_protect�s��	rcC�|dkrtd��t|d�S)z�
    Enable termination protection on a node

    CLI Example:

    .. code-block:: bash

        salt-cloud -a enable_term_protect mymachine
    r��BThe enable_term_protect action must be called with -a or --action.r6�rr�r'r�r
r
r�enable_term_protect��

�
r cCr)z�
    Disable termination protection on a node

    CLI Example:

    .. code-block:: bash

        salt-cloud -a disable_term_protect mymachine
    r�r�falserrr
r
r�disable_term_protect�r!r#cC�N|dkrtd��t|�d}d|d�}tj|t�t�dtdd�}t||dd	�S)
�6
    Enable/disable detailed monitoring on a node
    r�rr�ZUnmonitorInstancesr�Tr�rr�rr�rLr�rRr�rrr�r
r
r�disable_detailed_monitoring��
�	r'cCr$)
r%r�rr�ZMonitorInstancesr�Tr�rrr&r�r
r
r�enable_detailed_monitoring$r(r)cCs|dkrtd��|si}|�dd�}|�dd�}|�dd�}|dur(t|�d}d|d	�}tj|t�t�td
d�}|dd
dd}t|dt	�sQ|dg|d<g}	t
|d�D]1\}
}|d}|durj||krjqY|durw||ddkrwqY||dd|ddd�}
|	�|
�qY|	S)z�
    Do not delete all/specified EBS volumes upon instance termination

    CLI Example:

    .. code-block:: bash

        salt-cloud -a show_delvol_on_destroy mymachine
    r�zEThe show_delvol_on_destroy action must be called with -a or --action.r�Nr�r�r�r�r�r�r�rr=r)rTrUrVr��deleteOnTermination)�device_namer�r*)rrKr�rLr�rRr�rr$r%rlr&)r'r�r�r�r�r�rGr+�blockmapr,rr)r+r�r
r
r�show_delvol_on_destroy<sF�
�

�r-cC�@|dkrtd��|si}|�dd�}|�dd�}t|||dd�S)z�
    Do not delete all/specified EBS volumes upon instance termination

    CLI Example:

    .. code-block:: bash

        salt-cloud -a keepvol_on_destroy mymachine
    r�zAThe keepvol_on_destroy action must be called with -a or --action.r�Nr�r"�r'r�r�r�rrKr��r'r�r�r�r�r
r
r�keepvol_on_destroy{�
�r2cCr.)z�
    Delete all/specified EBS volumes upon instance termination

    CLI Example:

    .. code-block:: bash

        salt-cloud -a delvol_on_destroy mymachine
    r�z@The delvol_on_destroy action must be called with -a or --action.r�Nr�r6r/r0r1r
r
r�delvol_on_destroy�r3r4c
Cs.|st|�d}|rtj|t�t�tdd�}nd|d�}tj|dt�t�tdd�\}}|dd	d
d}d|d
�}t|d
t�sH|d
g|d
<t|d
�D].\}	}
|
d}|dur_||kr_qN|durl||
ddkrlqN||d|	�d�<||d|	�d�<qNtj|dt�t�tdd�|||d�}t	||dd�S)Nr�r�)rnr*rqr�r�r�r�T�ror*rqr�r�rr=r)rTr�r�rrUrVr�r[r\z.Ebs.DeleteOnTerminationr)r�r�r�r�r�)
r�rLr�rRr�rr$r%rlr-)
r'r�r�r�rrnr+rGr,rr)r+r�r
r
rr��sR	�

�	
�	r�c		Cs^|dkrt�d�dSd|vrt�d�dS|�dd�}|sEd|vr)t�d	�dSd
|vr4t�d�dS|d
|�dd
�|dd�d�g}t|t�sM|g}d|dd�}|�td|��d
|vrf|d
|d<d|vrp|d|d<d|vrz|d|d<d|vr�|d|d<t�|�tj	|ddt
�t�tdd�}i}|dD]}|�
�D]\}}|||<q�q�|S)z�
    Create an ami from a snapshot

    CLI Example:

    .. code-block:: bash

        salt-cloud -f register_image my-ec2-config ami_name=my_ami description="my description"
                root_device_name=/dev/xvda snapshot_id=snap-xxxxxxxx
    rF�@The create_volume function must be called with -f or --function.FZami_namez0ami_name must be specified to register an image.�block_device_mappingN�snapshot_idzKsnapshot_id or block_device_mapping must be specified to register an image.Zroot_device_namezProot_device_name or block_device_mapping must be specified to register an image.Zvolume_typeZgp2)�
VolumeType�
SnapshotId)rWZEbsZ
RegisterImage)r�r�rPZRootDeviceName�descriptionr Zvirtualization_typeZVirtualizationType�architectureZArchitectureTr��rorpr*rqr�r�r)rYr@rKr$r%r(r)rZrLr�rRr�rr,)	r�r�r8rGr+�r_data�dr.r:r
r
r�register_image�sh

��
���


�

�rAcK�
t|d�S)zh
    Wrapper around create_volume.
    Here just to ensure the compatibility with the cloud module.
    rF)r��r�r
r
r�
volume_create<�
rDcCs�d|dd�}d|vr|d|d<d|vr|d|d<d|vr%|d|d	<d
|vr9|�dd���dvr9|d
|d
<d|vrQd|vrQ|d|d<d|vrQ|d|d<|S)NZCreateVolumer)r�ZAvailabilityZonerNZSizer�r;rGr:r�Zstandard�Zio1Zio2ZIopsr�Z	Encryptedr�ZKmsKeyId)rKrC)r�rGr
r
r�_load_paramsDsrGc	Csf|dkrt�d�dSd|vrt�d�dSd|vr%d|vr%t�d�dS|�d	���d
vr9d|vr9t�d�dSd
|vrEd|vrEd|d
<t|�}t�|�tj|ddt�t	�t
dd�}i}|dD]}|��D]\}}|||<qhqb|d}	d|vr�t|dt
�r�tjj�|d�}
n|d}
t|
t�r�t|
|	dt�d�}||d<|r�tjjjtd|	i|ddd�|S)aW
    Create a volume.

    zone
        The availability zone used to create the volume. Required. String.

    size
        The size of the volume, in GiBs. Defaults to ``10``. Integer.

    snapshot
        The snapshot-id from which to create the volume. Integer.

    type
        The volume type. This can be ``gp2`` for General Purpose SSD, ``io1`` or
        ``io2`` for Provisioned IOPS SSD, ``st1`` for Throughput Optimized HDD,
        ``sc1`` for Cold HDD, or ``standard`` for Magnetic volumes. String.

    iops
        The number of I/O operations per second (IOPS) to provision for the volume,
        with a maximum ratio of 50 IOPS/GiB. Only valid for Provisioned IOPS SSD
        volumes. Integer.

        This option will only be set if ``type`` is also specified as ``io1`` or
        ``io2``

    encrypted
        Specifies whether the volume will be encrypted. Boolean.

        If ``snapshot`` is also given in the list of kwargs, then this value is ignored
        since volumes that are created from encrypted snapshots are also automatically
        encrypted.

    tags
        The tags to apply to the volume during creation. Dictionary.

    call
        The ``create_volume`` function must be called with ``-f`` or ``--function``.
        String.

    wait_to_finish
        Whether or not to wait for the volume to be available. Boolean. Defaults to
        ``False``.

    CLI Examples:

    .. code-block:: bash

        salt-cloud -f create_volume my-ec2-config zone=us-east-1b
        salt-cloud -f create_volume my-ec2-config zone=us-east-1b tags='{"tag1": "val1", "tag2", "val2"}'
    rFr7Frz:An availability zone must be specified to create a volume.r�r�z8If a KMS Key ID is specified, encryption must be enabledrGrFr�z0Iops must be specified for types 'io1' and 'io2'rNr��10Tr�r>rr�rr�)rr�r�r*r�rmr��Zfunr�Zfun_callZargument_being_watchedZrequired_argument_response)rYr@rKrCrGrZrLr�rRr�rr,r$r�rr\r�r�r�r�r��run_func_until_ret_arg�describe_volumes)r�r�r�rGr+r?r@r.r:r�rZnew_tagsr
r
rr�]sb3




�

�

��r�cCs<tj|dt�t�tdd�}|drt�d|d|�dS|S)NTr�r5rz3Error attaching volume %s to instance %s. Retrying!r�F)rLr�rRr�rrYr�)rG�kwsr�r+r
r
r�__attach_vol_to_instance�s ��rMcCs�|dkrtd��|si}d|vr|d}|r|st|�d}|s)|s)t�d�dSd|vr4t�d�dSd	|vr?t�d
�dSd|d||d	d�}t�|�t�}tjjj	t
|||ftjd
|t
dd�tjd|t
dd�tjd|t
dd�d�}|S)z(
    Attach a volume to an instance
    r�z<The attach_volume action must be called with -a or --action.r�r��,Either a name or an instance_id is required.Fr��A volume_id is required.r�z%A device is required (ex. /dev/sdb1).ZAttachVolume)r��VolumeIdrZDevicer�r�r�r�r�r�rr�)rr�rYr@rZr
rr\r�r�rMrr�r)r'r�r�r�rGr�r+r
r
rr��sP�


�
����r�cCs|si}t||�S)zo
    Wrapper around describe_volumes.
    Here just to keep functionality.
    Might be depreciated later.
    �rKr�r
r
r�show_volume s
rRcCsZ|dkrtd��|si}d|vrt�d�dSd|dd�}tj|dt�t�td	d
�}|S)z*
    Detach a volume from an instance
    r�z<The detach_volume action must be called with -a or --action.r�rOFZDetachVolume�r�rPTr�r5)rrYr@rLr�rRr�r�r'r�r�r�rGr+r
r
r�
detach_volume,s&�
�rUcCsJ|si}d|vrt�d�dSd|dd�}tj|dt�t�tdd�}|S)	z
    Delete a volume
    r�rOFZDeleteVolumerSTr�r5�rYr@rLr�rRr�rrTr
r
r�
delete_volumeIs
�rWcKrB)zk
    Wrapper around describe_volumes.
    Here just to ensure the compatibility with the cloud module.
    rFrQrCr
r
r�volume_listarErXcCs�|dkrt�d�dS|si}ddi}d|vr.|d�d�}t|�D]\}}||d|��<q"t�|�tj|d	t�t�t	d
d�}|S)z�
    Describe a volume (or volumes)

    volume_id
        One or more volume IDs. Multiple IDs must be separated by ",".

    TODO: Add all of the filters.
    rFzCThe describe_volumes function must be called with -f or --function.Fr�ZDescribeVolumesr�r�z	VolumeId.Tr�r5�
rYr@r!rlrZrLr�rRr�r)r�r�rGr�Zvolume_indexr+r
r
rrKis(	

�rKcC�`|dkrt�d�dS|si}d|vrt�d�dSd|dd�}tj|dt�t�td	d
�}|S)z
    Create an SSH keypair
    rFzAThe create_keypair function must be called with -f or --function.Fr��A keyname is required.Z
CreateKeyPair�r�rOTr�r5rV�r�r�rGr+r
r
r�create_keypair��$

�r^cCs�|dkrt�d�dS|si}d|vrt�d�dSd|vr%t�d�dSd|dd	�}|d}tj�|�rWtjj�|d
��}tjj	�
|���}Wd�n1sRwY|durbt�
|�|d<tj|d
t�t�tdd�}|S)zC
    Import an SSH public key.

    .. versionadded:: 2015.8.3
    rFzAThe import_keypair function must be called with -f or --function.Fr�r[�filezA public key file is required.Z
ImportKeyPairr\rMNZPublicKeyMaterialTr�r5)rYr@r�rWrtrr\rurvrwrxryrzr{rLr�rRr�r)r�r�rGZpublic_key_filer�Z
public_keyr+r
r
r�import_keypair�s8


��racCrZ)z,
    Show the details of an SSH keypair
    rFz?The show_keypair function must be called with -f or --function.Fr�r[ZDescribeKeyPairs)r�z	KeyName.1Tr�r5rVr]r
r
r�show_keypair�r_rbcCrZ)z
    Delete an SSH keypair
    rFzAThe delete_keypair function must be called with -f or --function.Fr�r[Z
DeleteKeyPairr\Tr�r5rVr]r
r
r�delete_keypair�r_rcc	Cs�|dkrtd��|duri}|�dd�}|�dd�}|dur"td��d||d	�}t�|�tj|d
d
t�t�tdd�d
}i}|D]}|�	�D]\}	}
|
||	<qGqAd|vri|d}|rit
jjj
td|i|ddd�|S)a�
    Create a snapshot.

    volume_id
        The ID of the Volume from which to create a snapshot.

    description
        The optional description of the snapshot.

    CLI Exampe:

    .. code-block:: bash

        salt-cloud -f create_snapshot my-ec2-config volume_id=vol-351d8826
        salt-cloud -f create_snapshot my-ec2-config volume_id=vol-351d8826 \
            description="My Snapshot Description"
    rFzBThe create_snapshot function must be called with -f or --function.Nr�r<r?z3A volume_id must be specified to create a snapshot.ZCreateSnapshot)r�rPr Tr�r>rZ
snapshotIdr9rmZ	completedrI)rrKrYrZrLr�rRr�rr,rr\r�rJ�describe_snapshots)r�r�r�r�r<rGr+r?r@r.r:r9r
r
r�create_snapshotsT��
��

��recCsp|dkrt�d�dSd|vrt�d�dSddi}d|vr$|d|d<t�|�tj|d	t�t�td
d�}|S)z
    Delete a snapshot
    rFzBThe delete_snapshot function must be called with -f or --function.Fr9z5A snapshot_id must be specified to delete a snapshot.r�ZDeleteSnapshotr;Tr�r5�rYr@rZrLr�rRr�rr]r
r
r�delete_snapshotSs&


�rgcCs�|dkrt�d�dSd|vrt�d�dSd|vr!t�d�dSd|vr)d	|d<d
di}d|vr7|d|d<d|vrA|d|d
<d|vrK|d|d<t�|�tj|dt�t�tdd�}|S)z
    Copy a snapshot
    rFz@The copy_snapshot function must be called with -f or --function.FZ
source_regionz5A source_region must be specified to copy a snapshot.Zsource_snapshot_idz:A source_snapshot_id must be specified to copy a snapshot.r<r?r�ZCopySnapshotZSourceRegionZSourceSnapshotIdr Tr�r5rfr]r
r
r�
copy_snapshotqs8



�rhc
Cs�|dkrt�d�dSddi}d|vr|d|d<d|vr4|d�d�}t|�D]\}}||d	|��<q(d
|vrO|d
�d�}t|�D]\}}||d|��<qCd|vrj|d�d�}	t|	�D]\}
}||d
|
��<q^t�|�tj|dt�t�t	dd�}|S)a�
    Describe a snapshot (or snapshots)

    snapshot_id
        One or more snapshot IDs. Multiple IDs must be separated by ",".

    owner
        Return the snapshots owned by the specified owner. Valid values
        include: self, amazon, <AWS Account ID>. Multiple values must be
        separated by ",".

    restorable_by
        One or more AWS accounts IDs that can create volumes from the snapshot.
        Multiple aws account IDs must be separated by ",".

    TODO: Add all of the filters.
    rFzDThe describe_snapshot function must be called with -f or --function.Fr�ZDescribeSnapshots�snapshot_idsr9r�zSnapshotId.r�zOwner.�
restorable_byz
RestorableBy.Tr�r5rY)
r�r�rGriZsnapshot_indexr9ZownersZowner_indexr�Zrestorable_bysZrestorable_by_indexrjr+r
r
rrd�s<�
�rdc	Cs�|dkrtd��|durt�}|st|�d}|duri}|dur,d|vr,|d}|d=d|d�}i}tj|d|t�td	d
�}|D]*}tt|�	���dkr[t
�tt|�����|d<qAtt|����|tt|�	���<qA|S)
z�
    Show the console output from the instance.

    By default, returns decoded data, not the Base64-encoded data that is
    actually returned from the EC2 API.
    r�zAThe get_console_output action must be called with -a or --action.Nr�r�ZGetConsoleOutputr6Tr�rr�r�)
rrRr�rLr�r�rrrry�binascii�
a2b_base64rz)	r'r*r�r�r�rGr�r+r)r
r
rr��s:
�
�	"r�cCs`|dkrtd��|st|�d}|duri}|dur%d|vr%|d}|d=d|d�}i}tj|dt�t�td	d
�}|D]}tt|�	���|tt|�
���<q;tjj
sad|vsZd|vr_t�d
�|Sd|vr�d|vr�tjj�|dd��}tjj�|���|d<Wd�n1s�wYd|vr�|�dd�}	|	dur�|d}
t�|	�}	tj�|
|	�|d<|S)a�
    Return password data for a Windows instance.

    By default only the encrypted password data will be returned. However, if a
    key_file is passed in, then a decrypted password will also be returned.

    Note that the key_file references the private key that was used to generate
    the keypair associated with this instance. This private key will _not_ be
    transmitted to Amazon; it is only used internally inside of Salt Cloud to
    decrypt data _after_ it has been received from Amazon.

    CLI Examples:

    .. code-block:: bash

        salt-cloud -a get_password_data mymachine
        salt-cloud -a get_password_data mymachine key_file=/root/ec2key.pem

    Note: PKCS1_v1_5 was added in PyCrypto 2.5
    r�z@The get_password_data action must be called with -a or --action.r�Nr�ZGetPasswordDatar6Tr�rrr�z8No crypto library is installed, can not decrypt passwordrMr�r�)rr�rLr�rRr�rrrrzryrrrrYr�r\rurvrwrxryrKrz�	b64decodeZpwdata_decrypt)r'r�r�r�rGr�r+r)Zkf_ZpwdataZrsa_keyr
r
rr�sP�
�	"
�
r�cCs\ddddddd�}|duri}d	|vr!|D]	}t|||�qdSt||d	|d	�dS)
a 
    Download most recent pricing information from AWS and convert to a local
    JSON file.

    CLI Examples:

    .. code-block:: bash

        salt-cloud -f update_pricing my-ec2-config
        salt-cloud -f update_pricing my-ec2-config type=linux

    .. versionadded:: 2015.8.0
    z6https://a0.awsstatic.com/pricing/1/ec2/linux-od.min.jsz5https://a0.awsstatic.com/pricing/1/ec2/rhel-od.min.jsz5https://a0.awsstatic.com/pricing/1/ec2/sles-od.min.jsz6https://a0.awsstatic.com/pricing/1/ec2/mswin-od.min.jsz9https://a0.awsstatic.com/pricing/1/ec2/mswinSQL-od.min.jsz<https://a0.awsstatic.com/pricing/1/ec2/mswinSQLWeb-od.min.js)�linux�rhel�sles�mswin�mswinsql�mswinsqlwebNrG)�_parse_pricing)r�r�Zsources�sourcer
r
r�update_pricingXs�	�rvcCs\tj|dd�}g}d}t�td|d�}|���d��d�}dD]}|�|d|�d��}q d	D]}|�|d|�d��}|�d|�d
�d|�d��}q/|�dd�}i}t	j
j�|�}|d
dD]}i}	|dD]}
|
dD]}||	|d<qmqg|	||d<q_t
j�tdd|�d��}t	j
j�|d��}
t	j
j�||
�Wd�dS1s�wYdS)z`
    Download and parse an individual pricing file from AWS

    .. versionadded:: 2015.8.0
    T)r"r?r"z);z	callback()�versrZrate�valueColumnsZ
currencies�
instanceTypesrGZECUZ	storageGBr'ZvCPUZ	memoryGiBZ
storageGiB�USD�")rvZpricerNz"szs"z""r�regionsryr�rNrv�cachedir�ec2-pricing-�.p�wN)�httpr��re�sub�
JS_COMMENT_REr[�rstrip�lstriprbrr\�json�loadsr�rW�joinrrurv�msgpack�dump)r�r'Zprice_jsr,Zcurrent_item�keywordr|Z
price_jsonrvr�ZityperNZoutfileZfhor
r
rrtys6�
��rtc
Cs�td�|di�}|sddiS|�dd�}|�d�}t|�dks'|d	d
kr+ddiS|�dd
�}td|id�}|d}|�dd�dkrx|�dd�dkrg|�dd�}d|��vrdd|��vrad}	n$d}	n!d}	n|�dd����d�rud}	nd}	n
|�dd�d kr�d!}	nd}	tj	�
td"d#|	�d$��}
tj	�|
�s�td%|	id�t
jj�|
d&��}t
jj�t
jj�|��}Wd
�n1s�wYt|�}
|�d'd
�}|d
ur�dd(iSz||
|}Wnty�dd)�||
�iYSwi}|�d*d+�r�||d,<d|d-<|�d.g�D]}|d-t�|d/�d0d��7<�qt�|d-�|d-<|d-d1|d2<|d2d3|d4<|d2d5|d6<|d4d7|d8<|d|iS)9a
    Show pricing for a particular profile. This is only an estimate, based on
    unofficial pricing sources.

    CLI Examples:

    .. code-block:: bash

        salt-cloud -f show_pricing my-ec2-config profile=my-profile

    If pricing sources have not been cached, they will be downloaded. Once they
    have been cached, they will not be updated automatically. To manually update
    all prices, use the following command:

    .. code-block:: bash

        salt-cloud -f update_pricing <provider>

    .. versionadded:: 2015.8.0
    Zprofilesr�rJz#The requested profile was not foundrqz0:0rr<rr	z,The requested profile does not belong to EC2r�NrFrZimageOwnerAliasr?r��platformZwindowsr<ZsqlZwebrsrrrqZ
imageLocationzamazon/suserprnZimageOwnerIdZ309956199498ror}r~rrGrMrNz-The requested profile does not contain a sizezaThe size ({}) in the requested profile does not have a price associated with it for the {} region�rawFZ_rawZper_hourrxZpricesrz�Zper_day�Zper_weekr�Z	per_month�4Zper_year)rrKr!rrrCr[r�r�rWr�r�rvrr\rurvrwrxr��loadrR�KeyErrorrX�decimalZDecimal)r�r�r�rqr(r�Z
image_dictZ
image_infoZimage_descriptionr'Z	pricefileZfhiZ	ec2_pricervrNr�r��colr
r
r�show_pricing�sl
���&r�c	C�|dkrtd��|si}d|vr|d}|r|st|�d}|s)|s)t�d�dSd|vr4t�d�dSd	||dd
�}tj|dt�t�dtd
d�}t�	|�|S)a*
    Associates the specified SSM document with the specified instance

    http://docs.aws.amazon.com/ssm/latest/APIReference/API_CreateAssociation.html

    CLI Examples:

    .. code-block:: bash

        salt-cloud -a ssm_create_association ec2-instance-name ssm_document=ssm-document-name
    r�zEThe ssm_create_association action must be called with -a or --action.r�r�rNFr��A ssm_document is required.ZCreateAssociation�r�rr�T�ssmr��rpr*rq�productr�r��
rr�rYr@rLr�rRr�rr��r'r�r�r�rGr|r
r
rr�s>
�

��
	r�c	Cr�)a3
    Describes the associations for the specified SSM document or instance.

    http://docs.aws.amazon.com/ssm/latest/APIReference/API_DescribeAssociation.html

    CLI Examples:

    .. code-block:: bash

        salt-cloud -a ssm_describe_association ec2-instance-name ssm_document=ssm-document-name
    r�zGThe ssm_describe_association action must be called with -a or --action.r�r�rNFr�r�ZDescribeAssociationr�Tr�r�r�r�r�r
r
r�ssm_describe_associationDs>�

��
	r�)NNNNFF)NNr�r�rr�r)NN)NNNTN)NT)NNNNNNN)NNNNNN)NNNNN)NNNN)NNN)NNNF)NNF)��__doc__rzrkrOr�r6r3r�r�r�r�r�r��urllib.parserSr�Zxml.etree.ElementTreeZetreeZElementTreerg�	functoolsrZsalt.configrZ
salt.cryptrZsalt.utils.awsr\rLZsalt.utils.cloudZsalt.utils.compatZsalt.utils.filesZsalt.utils.hashutilsZsalt.utils.httpr�Zsalt.utils.jsonZsalt.utils.msgpackZsalt.utils.stringutilsZsalt.utils.yamlZsalt.exceptionsrrrrrrr�ImportError�	getLogger�__name__rYZ
EC2_LOCATIONSr-r]rj�compile�Sr�rrrr
rr#r1r:r�r�r�r�r�r�r�r�r�r�rRr�r�r�r�rrr
rrrr�r�rrr2r'r3r+r;r*r@r)r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrr�rrrr
rrrr�rrr r#r'r)r-r2r4r�rArDrGr�rMr�rRrUrWrXrKr^rarbrcrergrhrdr�r�rvrtr�r�r�r
r
r
r�<module>s�O�
�
	
	(
�L
�
K
u%	
;
 	$%	
	
q	


'4
H
A~
�X
p

P
 #
�l
�.
�
3

_


"
&
)

)


*





?

�
>S
u

:



$

+


G

+;
�6
�
M!
6
_6