
    fW                     ,   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mZm	Z	m
Z
mZmZ d dlmZmZmZmZmZmZmZmZ d dlmZ d dlmZmZmZ  ej8                         Z ej<                   ej>                  e             Z!dZ" G d d	ejF                        Z$y)
    N)exists)AnyDictListOptionalTupleUnion)aptcontractevent_logger
exceptionshttpmessagessystemutil)base)ApplicationStatusCanDisableFailureCanDisableFailureReasonz<^linux-image-([\d]+[.-][\d]+[.-][\d]+-[\d]+-[A-Za-z0-9_-]+)$c            	           e Zd ZdZdZdZdZdZdZdZ	e
deeedf   fd       Ze
defd	       Ze
dee   fd
       ZdefdZe
ej*                  defd              Z	 d#dedeeee   f   f fdZd#dedefdZd#dZd Zd Zd Zd Z dee!ee"jF                     f   fdZ$d Z%	 d#de&ee'f   de&ee'f   dedef fdZ(	 	 	 d$deee      dededdfdZ)d#deddfd Z*	 d%d!edefd"Z+ xZ,S )&RepoEntitlementz1/etc/apt/sources.list.d/ubuntu-{name}.{extension}z$/etc/apt/preferences.d/ubuntu-{name}z	{}/ubuntuNFTreturnc                      y N selfs    </usr/lib/python3/dist-packages/uaclient/entitlements/repo.pyrepo_pin_priorityz!RepoEntitlement.repo_pin_priority4   s        c                     d}t        j                         j                  }|t        j                  v rd}| j
                  j                  | j                  |      S )Nsourceslist)name	extension)r   get_release_infoseriesr
   SERIES_NOT_USING_DEB822repo_file_tmplformatr$   )r   r%   r'   s      r   	repo_filezRepoEntitlement.repo_file8   sN    	((*11S000I""))tyyI)NNr    c                     g }| j                   j                  di       }|r9|j                  di       }t        j                  |j                  dg             }|}|S )zdebs to install on enablemententitlement
directivesadditionalPackages)entitlement_cfggetcopy)r   packagesr-   r.   additional_packagess        r   r3   zRepoEntitlement.packages@   s^     **..}bA$r:J"&))3R8# +Hr    c                     t        j                  t        | j                              }t        j                  |       |S )z%Check if system needs to be rebooted.)installed_pkgs)r   should_rebootsetr3   eventneeds_reboot)r   reboot_requireds     r   _check_for_rebootz!RepoEntitlement._check_for_rebootQ   s4     ..t}}-
 	?+r    c                      y r   r   r   s    r   repo_key_filezRepoEntitlement.repo_key_fileY   s     	r    ignore_dependent_servicesc                    t         |   |      \  }}|du r||fS | j                  s[| j                  rOdt	        t
        j                  t        j                  j                  | j                  | j                              fS ||fS )N)r?   Fentitlement_nametitle)supercan_disableoriginpurger   r   NO_PURGE_WITHOUT_ORIGINr   REPO_PURGE_FAIL_NO_ORIGINr*   rC   )r   r?   resultreason	__class__s       r   rE   zRepoEntitlement.can_disable^   s     ,&? - 
 U?6>!{{tzz!+CC66==)-4:: >   v~r    silentc                 Z   | j                  |       | j                  r| j                  rt        | j                        dkD  rLt
        j                  t        j                  j                  dj                  | j                                     t
        j                  t        j                  j                  | j                               y| j                          t
        j                  t        j                  j                  | j                               | j                  d       y)	zEnable specific entitlement.

        @return: True on success, False otherwise.
        @raises: UbuntuProError on failure to install suggested packages
        rM   r    r3   rC   install)	operationT)setup_apt_configsupports_access_onlyaccess_onlylenr3   r9   infor   SKIPPING_INSTALLING_PACKAGESr*   joinACCESS_ENABLED_TMPLrC   install_packagesENABLED_TMPL_check_for_reboot_msg)r   rM   s     r   _perform_enablezRepoEntitlement._perform_enablet   s     	V,$$)9)94==!A%

99@@!$$--!8 A 
 JJx33:::LM
  !!#JJx,,33$**3EF&&&;r    c                    | j                   r| j                  rt        t        j                         t                t        j                  | j                        }| j                  |      syg }g }|D ]S  }t        j                  || j                        }|r|j                  |t        |      f       C|j                  |       U | j                  ||      syt        | d      r| j                          | j                  |       | j                   r.| j                  r"| j                         | j!                         y)NF)exclude_originremove_packagesrO   T)rG   rF   printr   PURGE_EXPERIMENTALr
    get_installed_packages_by_originpurge_kernel_checkget_remote_versions_for_packageappendmaxprompt_for_purgehasattrrc   remove_apt_configexecute_reinstallexecute_removal)r   rM   repo_origin_packagespackages_to_reinstallpackages_to_removepackagealternativess          r   _perform_disablez RepoEntitlement._perform_disable   s%   ::$++(--.G#&#G#G$  **+?@$&!!#/ 7"BBDKK    *00 #l"34 '--g67 (("$9 4*+  "f-::$++""#89  !34r    c                    g }|D ]I  }t        j                  t        |j                        }|s*|j	                  |j                  d             K |rt        t        j                  j                  | j                               t        dj                  |             t        j                         j                  }t        t        j                  j                  |             t        j                          }|D cg c]  }||vr|
 }}|st        t        j"                         yt%        j&                  t        j(                        syyc c}w )a*  
        Checks if the purge operation involves a kernel.

        When package called 'linux-image-*' is in the package list, warn the
        user that a kernel is being removed. Then, show the user what the
        current kernel is.

        If the current kernel is to be removed, and there are no other valid
        Ubuntu Kernels installed in the system, return False to abort the
        operation.

        If there is another Ubuntu kernel - besides the one installed - then
        prompt the user for confirmation before proceeding.
           servicerP   )kernel_versionFT)researchRE_KERNEL_PKGr$   ri   grouprd   r   PURGE_KERNEL_REMOVALr*   rC   r[   r   get_kernel_infouname_releasePURGE_CURRENT_KERNELget_installed_ubuntu_kernelsPURGE_NO_ALTERNATIVE_KERNELr   prompt_for_confirmationPURGE_KERNEL_CONFIRMATION)	r   package_listlinux_image_versionsrs   mcurrent_kernelinstalled_kernelsversionalternative_kernelss	            r   rg   z"RepoEntitlement.purge_kernel_check   s)     "# 	8G		-6A$++AGGAJ7	8  (//66tzz6JK#((/01#335CCN--44#1 5  !' C C E  1#"66 # # 'h::;//22 #s   ?Ec                    d}|rHt        t        j                         t        j                  |D cg c]  }|j
                   c}       d}|rMt        t        j                         t        j                  |D cg c]  \  }}|j
                   c}}       d}|r#t        j                  t        j                        S yc c}w c c}}w )NFT)	rd   r   WARN_PACKAGES_REMOVALr   print_package_listr$   WARN_PACKAGES_REINSTALLr   PROCEED_YES_NO)r   rr   rq   promptrs   _s         r   rk   z RepoEntitlement.prompt_for_purge   s    (001##-?@'@ F (223##2GH,7AH F//0G0GHH A Is   C<C
c                     t        j                         }|D cg c]  }|j                  |v r|j                   }}|r5t        j                  |t        j
                  j                  |             y y c c}w )NrQ   )r
   get_installed_packages_namesr$   purge_packagesr   UNINSTALLING_PACKAGES_FAILEDr*   )r   rr   installed_packagesrs   	to_removes        r   ro   zRepoEntitlement.execute_removal   s    
 !==? .
||11 LL
	 

 55<<& =  
s   !A4c                     t        j                         }|D cg c]9  \  }}|j                  |v r&dj                  |j                  |j                        ; }}}|rt        j
                  |       y y c c}}w )Nz{}={})r
   r   r$   r*   ver_strreinstall_packages)r   rq   r   rs   r   to_reinstalls         r   rn   z!RepoEntitlement.execute_reinstall  ss     !==? '<
"'||11 NN7<<9
 

 ""<0 
s   >A4c                 l   t         j                  t        j                  j	                  | j
                        f}| j                  }|j                  di       j                  di       }|j                  d      }|s:t         j                  t        j                  j	                  | j
                        fS t        j                  t        j                        }t        j                  | j                  j	                  |      |      }|r:t         j                  t        j                   j	                  | j
                        f}| j"                  rc| j$                  D ]T  }t        j&                  |      rt         j                  t        j(                  j	                  | j*                  |      fc S  |S )NrR   r-   r.   aptURL)	error_msg)ry   rs   )r   DISABLEDr   SERVICE_NOT_CONFIGUREDr*   rC   r0   r1   NO_APT_URL_FOR_SERVICEr
   get_apt_cache_policyAPT_POLICY_FAILEDr{   r|   repo_url_tmplENABLEDSERVICE_IS_ACTIVEcheck_packages_are_installedr3   is_installed SERVICE_DISABLED_MISSING_PACKAGEr$   )r   current_statusr0   r.   repo_urlpolicymatchrs   s           r   application_statusz"RepoEntitlement.application_status  sp    &&++222D

 ..$((;??"

 >>(+!**//66TZZ6H  ))H4N4NO		$,,33H=vF!))**11

1CN
 ,,== ''0)22 AAHH$(IIw I   r    c                     | j                   }t        d t        j                  |      j	                         j                  d      D              ry|syt        |t        j                  |      v       S )zCheck if apt url delta should be applied.

        :param apt_url: string containing the apt url to be used.

        :return: False if apt url is already found on the source file.
                 True otherwise.
        c              3   >   K   | ]  }|j                  d         yw)#N)
startswith).0lines     r   	<genexpr>z<RepoEntitlement._check_apt_url_is_applied.<locals>.<genexpr>J  s!      
 OOC 
s   
FT)r+   allr   	load_filestripsplitbool)r   apt_urlapt_files      r   _check_apt_url_is_appliedz)RepoEntitlement._check_apt_url_is_applied?  sm     >>  
((288:@@F
 
   Gv//99::r    orig_accessdeltasallow_enablec                    t         |   |||      ry|j                  di       }|j                  di       }|j                  d      }|j                  d      }| j                  j	                  d      }|r|r| j                         }	n| j                         \  }	}
|	t        j                  k(  ry| j                  |      st        j                  d| j                  |       t        j                  t        j                  j!                  | j                  	             |j                  di       }|j                  di       j                  d      }|r t#        j$                  | j&                  |       | j)                          | j+                          |rjt        j                  d
|       t        j                  t        j,                  j!                  dj/                  |                   | j1                  |       y)a1  Process any contract access deltas for this entitlement.

        :param orig_access: Dictionary containing the original
            resourceEntitlement access details.
        :param deltas: Dictionary which contains only the changed access keys
        and values.
        :param allow_enable: Boolean set True if allowed to perform the enable
            operation. When False, a message will be logged to inform the user
            about the recommended enabled service.

        :return: True when delta operations are processed; False when noop.
        Tr-   r.   r   r/   zstatus-cacheFz.New aptURL, updating %s apt sources list to %srx   z%New additionalPackages, installing %r, rQ   )r   )rD   process_contract_deltasr1   cfg
read_cache"_check_application_status_on_cacher   r   r   r   LOGrY   r$   r9   r   REPO_UPDATING_APT_SOURCESr*   r
   remove_auth_apt_repor+   rm   rU    REPO_REFRESH_INSTALLING_PACKAGESr[   r]   )r   r   r   r   delta_entitlementdelta_directivesdelta_apt_urldelta_packagesstatus_cacher   r   orig_entitlementold_urlrL   s                r   r   z'RepoEntitlement.process_contract_deltasY  s   $ 7*;M"JJ}b9,00rB(,,X6)--.BCxx**>:!%!H!H!J$($;$;$=!!2!;!;;--m<HH@		
 JJ2299$))9L  +}bA&**<<@@JG((A""$!!#HH<nMJJ99@@!YY~6 A 
 !!~!>r    r   cleanup_on_failureverbosec                    |s| j                   }|sy| j                  j                  dg       }t        j                  |      sy	 | j                          |r=t        j                  t        j                  j                  | j                               | j                  r	ddi}g d}nd}g }	 t!        j"                  |||       y# t        j                  $ r |r| j                           w xY w# t        j                  $ rQ t        j                  t        j$                  j                  | j                               |r| j                           w xY w)a)  Install contract recommended packages for the entitlement.

        :param package_list: Optional package list to use instead of
            self.packages.
        :param cleanup_on_failure: Cleanup apt files if apt install fails.
        :param verbose: If true, print messages to stdout
        Npre_installrR   DEBIAN_FRONTENDnoninteractive)z--allow-downgradesz$-o Dpkg::Options::="--force-confdef"z$-o Dpkg::Options::="--force-confold")r3   apt_optionsoverride_env_vars)r3   	messagingr1   r   handle_message_operations_update_sources_listr   UbuntuProErrorrm   r9   rY   r   INSTALLING_SERVICE_PACKAGESr*   rC   apt_noninteractiver
   run_apt_install_commandENABLE_FAILED)r   r   r   r   msg_opsr   r   s          r   r]   z RepoEntitlement.install_packages  s6    ==L..$$]B7--g6	%%' JJ44;;$**;M ""!24D EK !%K
	''%'"3- (( 	!&&(	6 (( 	JJx--444::4FG!&&(		s   C .C1 'C.1A$Ec                 
   d}d}d}| j                   j                  s| j                   j                  rt        j                  d| j                   j                  t        j
                        }t        j                  d| j                   j                  t        j                        }t        j                  j                  }n| j                   j                  s| j                   j                  rt        j                  d| j                   j                  t        j
                        }t        j                  d| j                   j                  t        j                        }t        j                  j                  }t        j                  |||       | j                  }| j                  }|d   j!                  di       }|d   j!                  di       }|j!                  d      }	|	s| j                   j"                  d	   }
|j!                  d
      sNt%        j&                  | j                         }|j)                  |
| j*                        }|r|j!                  d      }	|	s"|
}	t,        j/                  d| j0                         |j!                  d      }|s t3        j4                  | j*                        |j!                  d      }|s t3        j6                  | j*                        |j!                  d      }|s t3        j8                  | j*                        | j:                  r| j<                  s+t3        j>                  | j*                  | j0                        | j@                  jC                  | j*                        }t        jD                  ||| j<                  | j:                         g }tG        t        jH                        s|jK                  d       tG        t        jL                        s|jK                  d       |r[|sBtN        jQ                  tR        jT                  jC                  djW                  |                   	 t        jX                  |       t        j^                  || j`                  jC                  |      |	|| jb                         |s=tN        jQ                  tR        jd                  jC                  | j0                               	 t        jf                  |       y# t2        jZ                  $ r | j]                           w xY w# t2        jZ                  $ r | j]                  d        w xY w)zSetup apt config based on the resourceToken and directives.
        Also sets up apt proxy if necessary.

        :raise UbuntuProError: on failure to setup any aspect of this apt
           configuration
        Nr   https)
http_proxyhttps_proxyproxy_scoper-   r.   obligationsresourceTokenmachineTokenenableByDefaultzWNo resourceToken present in contract for service %s. Using machine token as credentialsaptKeyrB   r   suitesrA   r$   zapt-transport-httpszca-certificatesr   rQ   F)run_apt_update)4r   global_apt_http_proxyglobal_apt_https_proxyr   validate_proxyPROXY_VALIDATION_APT_HTTP_URLPROXY_VALIDATION_APT_HTTPS_URLr
   AptProxyScopeGLOBALua_apt_http_proxyua_apt_https_proxyUACLIENTsetup_apt_proxyr+   r0   r1   machine_tokenr   UAContractClientget_resource_machine_accessr$   r   warningrC   r   RepoNoAptKeyMissingAptURLDirectiveRepoNoSuitesr   rF   RepoPinFailNoOriginrepo_pref_file_tmplr*   add_ppa_pinningr   APT_METHOD_HTTPS_FILEri   CA_CERTIFICATES_FILEr9   rY   r   INSTALLING_PACKAGESr[   r   r   rm   add_auth_apt_repor   r>   APT_UPDATING_LISTupdate_sources_list)r   rM   r   r   scoperepo_filenameresource_cfgr.   r   tokenr   clientmachine_accessr   r   repo_suitesrepo_pref_fileprerequisite_pkgss                     r   rU   z RepoEntitlement.setup_apt_config  s<    
88))TXX-L-L,,..22J
 --//33K
 %%,,EXX''488+F+F,,**22J
 --++33K
 %%..E!{	
 ++!-044\2F
"=155mRH  1 HH22>BM??#45 "22488<!'!C!C!499" "*..?E%:JJ
 )))499EE>>(+33TYYOO nnX.))499EE!!;; 44%)YY**  "55<<$))<LN&&	 c//0$$%:;c../$$%67

0077!%+<!= 8 
++5FG 	%%h/	
 JJx1188djj8IJ	##M2# ,, &&($ (( 	""%"8	s   S4 T 4%T'Ur   c                    t        j                         j                  }| j                  }| j                  j
                  j                  | j                     j                  di       }|j                  di       }|j                  d      }|s t        j                  | j                        t        j                  ||| j                         t        j                  ||       | j                  r;| j                   j#                  | j                        }t        j$                  |       |r:|s#t&        j)                  t*        j,                         t        j.                          yy)zRemove any repository apt configuration files.

        :param run_apt_update: If after removing the apt update
            command after removing the apt files.
        r-   r.   r   r   r   N)r   r&   r'   r+   r   machine_token_fileentitlementsr$   r1   r   r  r
   r   r>   remove_apt_list_filesr   r  r*   ensure_file_absentr9   rY   r   APT_UPDATING_LISTSrun_apt_update_command)	r   r   rM   r'   r  r-   access_directivesr   r  s	            r   rm   z!RepoEntitlement.remove_apt_configO  s    ((*11hh11>>tyyIMM2
 (OOL"=$((233TYYOO  $:L:LM!!(F3!!!55<<$))<LN%%n5

8667&&( r    )F)NTT)TF)-__name__
__module____qualname__r)   r  r   rF   r   r   supports_purgepropertyr	   intstrr   r+   r   r3   r   r<   abcabstractmethodr>   r   r   r   rE   r`   ru   rg   rk   ro   rn   r   r   NamedMessager   r   r   r   r   r]   rU   rm   __classcell__)rL   s   @r   r   r   !   s   HN@M F  $)  N 5c4#8   O3 O O $s)   4  s    16)-	tX/00	1,d t ,'R0d(&1$	 (8+@+@"AA	B$L;< #	?#s(^? S#X? 	?
 
?F -1#'	9tCy)9 !9 	9
 
9vxt x xv ;@)")37)r    r   )%r(  r2   loggingr{   os.pathr   typingr   r   r   r   r   r	   uaclientr
   r   r   r   r   r   r   r   uaclient.entitlementsr   (uaclient.entitlements.entitlement_statusr   r   r   get_event_loggerr9   	getLoggerreplace_top_level_logger_namer!  r   r}   UAEntitlementr   r   r    r   <module>r6     s    
   	  : :	 	 	 '  	&%%'g:::8DE PJ	)d(( J	)r    