
    d7                        d dl Z d dlZd dlmZ d dlmc mc mZ d dlm	Z	m
Z
 d dlmZ d dlmc mZ d dlmZmZ d dlmZ dZdZd	Zd Zd
ZdZdZ edg d      Zd Zd
ZdZdZd Z dZ! G d de"      Z# G d de      Z$ G d de"      Z%y)    N)
namedtuple)	HttpErrorResourceGoneError)ustr)DataContractset_properties)FlexibleVersionz169.254.169.254z
2018-02-01z'http://{0}/metadata/{1}?api-version={2}         MetadataResult)successservice_errorresponsec                     t        |       S N)
ImdsClient)wireserver_endpoints    F/usr/lib/python3/dist-packages/azurelinuxagent/common/protocol/imds.pyget_imds_clientr      s    )**    a	  {
    "CANONICAL": {
        "UBUNTUSERVER": {
            "List": [
                "14.04.0-LTS",
                "14.04.1-LTS",
                "14.04.2-LTS",
                "14.04.3-LTS",
                "14.04.4-LTS",
                "14.04.5-LTS",
                "14.04.6-LTS",
                "14.04.7-LTS",
                "14.04.8-LTS",

                "16.04-LTS",
                "16.04.0-LTS",
                "18.04-LTS",
                "20.04-LTS",
                "22.04-LTS"
            ]
        }
    },
    "COREOS": {
        "COREOS": {
            "STABLE": { "Minimum": "494.4.0" }
        }
    },
    "CREDATIV": {
        "DEBIAN": { "Minimum": "7" }
    },
    "OPENLOGIC": {
        "CENTOS": {
            "Minimum": "6.3",
            "List": [
                "7-LVM",
                "7-RAW"
            ]
        },
        "CENTOS-HPC": { "Minimum": "6.3" }
    },
    "REDHAT": {
        "RHEL": {
            "Minimum": "6.7",
            "List": [
                "7-LVM",
                "7-RAW"
            ]
        },
        "RHEL-HANA": { "Minimum": "6.7" },
        "RHEL-SAP": { "Minimum": "6.7" },
        "RHEL-SAP-APPS": { "Minimum": "6.7" },
        "RHEL-SAP-HANA": { "Minimum": "6.7" }
    },
    "SUSE": {
        "SLES": {
            "List": [
                "11-SP4",
                "11-SP5",
                "11-SP6",
                "12-SP1",
                "12-SP2",
                "12-SP3",
                "12-SP4",
                "12-SP5",
                "12-SP6"
            ]
        },
        "SLES-BYOS": {
            "List": [
                "11-SP4",
                 "12",
                "12-SP1",
                "12-SP2",
                "12-SP3",
                "12-SP4",
                "12-SP5",
                "15",
                "15-SP1",
                "15-SP2",
                "15-SP3",
                "15-SP4",
                "15-SP5"
            ]
        },
        "SLES-SAP": {
            "List": [
                "11-SP4",
                "12",
                "12-SP1",
                "12-SP2",
                "12-SP3",
                "12-SP4",
                "12-SP5",
                "15",
                "15-SP1",
                "15-SP2",
                "15-SP3",
                "15-SP4",
                "15-SP5"
            ]
        },
        "SLE-HPC": {
           "List": [
               "15-SP1",
               "15-SP2",
                "15-SP3",
                "15-SP4",
                "15-SP5"
           ]
        }
    }
}c                       e Zd Zd Zd Zy)ImageInfoMatcherc                 8    t        j                  |      | _        y r   )jsonloadsdoc)selfr   s     r   __init__zImageInfoMatcher.__init__   s    ::c?r   c                 <    fd | j                   ||||g      S )Nc                 P   |j                  d      j                         }|y|| vryd| |   v r|d   | |   d   v ryd| |   v r t        j                  | |   d   |d         ryd| |   v r!	 t	        |d         t	        | |   d         k\  S  | |   |      S # t
        $ r Y w xY w)Nr   FListTMatchMinimum)popupperrematchr	   
ValueError)docikeyskey_is_match_walks      r   r-   z1ImageInfoMatcher.is_match.<locals>._is_match_walk   s    ((1+##%C{$c"tAw$s)F2C'C$s)#c71CT!W(MDI%*473tCyQZG[7\\\ "$s)T22 " s   -B 	B%$B%)r   )r   	publisherofferskuversionr-   s        @r   is_matchzImageInfoMatcher.is_match   s$    	3, dhh)UC(JKKr   N)__name__
__module____qualname__r   r2    r   r   r   r      s    #Lr   r   c                   f    e Zd Z ee      Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZed        Zed        Z	y)ComputeInfoNc                     || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        || _
        || _        || _        || _        || _        || _        || _        y r   )locationnamer/   osTypeplacementGroupIdplatformFaultDomainplatformUpdateDomainr.   resourceGroupNamer0   subscriptionIdtagsr1   vmIdvmSizevmScaleSetNamezone)r   r:   r;   r/   r<   r=   r>   placementUpdateDomainr.   r@   r0   rA   rB   r1   rC   rD   rE   rF   s                     r   r   zComputeInfo.__init__   s    $ !	
 0#6 $9!"!2,		,	r   c                 z    dj                  | j                  | j                  | j                  | j                        S )Nz{0}:{1}:{2}:{3})formatr.   r/   r0   r1   )r   s    r   
image_infozComputeInfo.image_info   s)     ''

DHHdll[[r   c           	         	 | j                   dk(  rt        S t        j                  j	                  | j                   | j
                  | j                  | j                        rt        S t        S # t        $ rL}t        j                  t        j                  dj                  t        |                   t         cY d}~S d}~ww xY w)aO  
        An integer value describing the origin of the image.

          0 -> unknown
          1 -> custom - user created image
          2 -> endorsed - See https://docs.microsoft.com/en-us/azure/virtual-machines/linux/endorsed-distros
          3 -> platform - non-endorsed image that is available in the Azure Marketplace.
         z>[PERIODIC] Could not determine the image origin from IMDS: {0}N)r.   IMDS_IMAGE_ORIGIN_CUSTOMr8   _ComputeInfo__matcherr2   r/   r0   r1   IMDS_IMAGE_ORIGIN_ENDORSEDIMDS_IMAGE_ORIGIN_PLATFORM	Exceptionloggerperiodic_warnEVERY_FIFTEEN_MINUTESrI   r   IMDS_IMAGE_ORIGIN_UNKNOWN)r   es     r   image_originzComputeInfo.image_origin   s    	-~~#//$$--dnndjj$((TXT`T`a1111 	-  !=!=!a!h!himnoip!qs,,	-s*   A- AA- 'A- -	C6AB=7C=C)NNNNNNNNNNNNNNNNN)
r3   r4   r5   r    ENDORSED_IMAGE_INFO_MATCHER_JSONrN   r   propertyrJ   rW   r6   r   r   r8   r8      sr     !ABI "&%)'+#' $ $#"H \ \ - -r   r8   c                   J    e Zd ZefdZd Zd Zd Zd Zd Z	d Z
ed        Zy	)
r   c                     || _         t        j                  dd| _        t        j                  dd| _        t        j                  d      | _        t        j                  d      | _	        || _
        y )NT)z
User-AgentMetadataz-.*HTTP Failed. GET http://[^ ]+ -- IOError .*z4.*HTTP Retry. GET http://[^ ]+ -- Status Code 429 .*)_api_versionrestutilHTTP_USER_AGENT_headersHTTP_USER_AGENT_HEALTH_health_headersr'   compile_regex_ioerror_regex_throttled_wireserver_endpoint)r   r   r1   s      r   r   zImdsClient.__init__  se    #"22

 #99 
 !jj)YZ "

+b c$7!r   c                 D    t         j                  ||| j                        S r   )BASE_METADATA_URIrI   r]   )r   endpointresource_paths      r   _get_metadata_urlzImdsClient._get_metadata_url  s     ''-ARARSSr   c                 V    | j                  ||      }t        j                  ||d      S )NF)headers	use_proxy)rk   r^   http_get)r   ri   rj   rm   urls        r   	_http_getzImdsClient._http_get  s)    $$X}=  gGGr   c                 B   	 | j                  |||      }|j                  dk\  r+t        dj                  |t        j                   |            fS t        j"                  |      r+t        dj                  |t        j                   |            fS t$        |j'                         fS # t        $ r t        dj                  |      fcY S t        $ r}t        |      }| j                  j                  |      rt        dj                  |      fcY d}~S | j                  j                  |      rOt        j                  t        j                  dj                  |             t        dj                  |      fcY d}~S t        dj                  ||      fcY d}~S d}~ww xY w)	a!  
        Get metadata from one of the IMDS endpoints.

        :param str endpoint: IMDS endpoint to call
        :param str resource_path: path of IMDS resource
        :param bool headers: headers to send in the request
        :return: Tuple<status:int, response:str>
            status: one of the following response status codes: IMDS_RESPONSE_SUCCESS, IMDS_RESPONSE_ERROR,
                    IMDS_CONNECTION_ERROR, IMDS_INTERNAL_SERVER_ERROR
            response: IMDS response on IMDS_RESPONSE_SUCCESS, failure message otherwise
        )ri   rj   rm   zCIMDS error in /metadata/{0}: HTTP Failed with Status Code 410: Gonez&IMDS error in /metadata/{0}: ThrottledNzI[PERIODIC] [IMDS_CONNECTION_ERROR] Unable to connect to IMDS endpoint {0}z:IMDS error in /metadata/{0}: Unable to connect to endpointz IMDS error in /metadata/{0}: {1}i  )rq   r   IMDS_INTERNAL_SERVER_ERRORrI   r   strre   r(   IMDS_RESPONSE_ERRORrd   rR   rS   rT   IMDS_CONNECTION_ERRORstatusr^   read_response_errorrequest_failedIMDS_RESPONSE_SUCCESSread)r   ri   rj   rm   resprV   msgs          r   _get_metadata_from_endpointz&ImdsClient._get_metadata_from_endpoint  s   	m>>8=Za>bD ;;#-/Q/X/X/<h>Z>Z[_>`0b b b ""4(&(J(Q(Q(5x7S7STX7Y)[ [ [ %diik11) ! 	K-/t/{/{  }J  0K  K  K 	ma&C$$**3/*,T,[,[\i,jjj""((-$$V%A%A%p%w%w  yA  &BC,.j.q.qr  /A  A  A-/Q/X/XYfhk/lll	ms<   B& & FF<FFA$F6F<FFFc                 6   |r| j                   n| j                  }t        }| j                  |||      \  }}|t        k(  r"| j
                  }| j                  |||      \  }}|t        k(  rt        dd|      S |t        k(  rt        dd|      S t        dd|      S )a,  
        Get metadata from IMDS, falling back to Wireserver endpoint if necessary.

        :param str resource_path: path of IMDS resource
        :param bool is_health: True if for health/heartbeat, False otherwise
        :return: instance of MetadataResult
        :rtype: MetadataResult
        TF)	rb   r`   IMDS_ENDPOINTr~   rv   rf   rz   r   rs   )r   rj   	is_healthrm   ri   rw   r|   s          r   get_metadatazImdsClient.get_metadata<  s     +4$&& 77-QXY**00H;;HmU\]LFD**!$t4411!%t44eUD11r   c                     | j                  dd      }|j                  st        |j                        t	        j
                  t        |j                  d            }t               }t        d||       |S )zt
        Fetch compute information.

        :return: instance of a ComputeInfo
        :rtype: ComputeInfo
        zinstance/computeFr   utf-8encodingcompute)	r   r   r   r   r   r   r   r8   r   )r   resultdatacompute_infos       r   get_computezImdsClient.get_computeS  sb     ""#5"G~~FOO,,zz$vAB"}y,5r   c                    | j                  dd      }|j                  s|j                   |j                  fS 	 t	        j
                  t        |j                  d            }	 | j                  |d	       | j                  |d	   d
       | j                  |d	   d
   d   d       | j                  |d	   d
   d   d       | j                  |d	   d
   d   d   d       | j                  |d	   d
   d   d   d   d   d       y# t        $ r&}ddj                  t        |            fcY d}~S d}~ww xY w# t        $ r}dt        |      fcY d}~S d}~ww xY w)a  
        Determines whether the metadata instance api returns 200, and the response
        is valid: compute should contain location, name, subscription id, and vm size
        and network should contain mac address and private ip address.
        :return: Tuple<is_healthy:bool, error_response:str>
            is_healthy: False when service returns an error, True on successful
                        response and connection failures.
            error_response: validation failure details to assist with debugging
        instanceTr   r   r   FzJSON parsing failed: {0}Nnetwork	interfacer   
macAddressipv4	ipAddressprivateIpAddress)TrL   )r   r   r   r   r   r   r   rQ   rI   check_fieldr)   )r   r   	json_datarV   vs        r   validatezImdsClient.validateg  sh    "":">~~,,,v>>	E

4'#JKI

	" Y	2Yy1;?Yy1+>qA<PYy1+>qA6JYy1+>qA&I;WYy1+>qA&I+VWXY[mn !  	E4;;DGDDD	E  	"$q'>!	"s<   *D %BD7 	D4D/)D4/D47	E EEEc                     || vs| |   t        dj                  |            t        | |         dk(  rt        dj                  |            y )NzMissing field: [{0}]r   zEmpty field: [{0}])r)   rI   len)dict_objfields     r   r   zImdsClient.check_field  sW     HUO$;3::5ABBx1$188?@@ %r   N)r3   r4   r5   
APIVERSIONr   rk   rq   r~   r   r   r   staticmethodr   r6   r   r   r   r     sB    4> 8TH"2H2.($L A Ar   r   )&r   r'   collectionsr   %azurelinuxagent.common.utils.restutilcommonutilsr^    azurelinuxagent.common.exceptionr   r   azurelinuxagent.common.futurer   azurelinuxagent.common.loggerrR   #azurelinuxagent.common.datacontractr   r   -azurelinuxagent.common.utils.flexible_versionr	   r   r   rh   rU   rM   rO   rP   r   rz   ru   rv   rs   r   rX   objectr   r8   r   r6   r   r   <module>r      s     	 " 8 8 I . . . L I!
=     ,.VW    +o$  dLv L<B-, B-JQA QAr   