
    Vh>                         d dl mZmZmZ eZd dlZd dlZd dlm	Z	 d dl
mZ d dlmZ g dZdZ	 d dlmZ d d	lmZ ddZd Z G d d      Zy# e$ r eZd
ZY w xY w)    )absolute_importdivisionprint_functionN)environ)string_types)AnsibleModule)INITREADYUSEDDISABLEDLOCKEDERRORCLONEDELETE	USED_PERSLOCKED_USEDLOCKED_USED_PERST)OneException)	OneServerFc                 L    fd |       }|rt        |      dk(  r|d   S |S )z7Flattens nested lists (with optional value extraction).c                 V    t        | t              rt        t        |       g       S | gS )N)
isinstancelistsummap)
to_flattenrecurses    u/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/general/plugins/module_utils/opennebula.pyr   zflatten.<locals>.recurse#   s)    4>z44Ps3w
+R0bWaVbb       r   )len)r   extractvaluer   s      @r   flattenr$   !   s.    cJE3u:?QxLr   c                 <    fddj                   |             S )z+Converts dictionary to OpenNebula template.c           
   3     K   t        | j                               D ]  \  }}|	t        |t              r*dj	                  |dj                   |                   Ct        |t              r1|D ]+  }dj	                  |dj                   |                   - t        |t              r5dj	                  ||j                  dd      j                  dd             dj	                  ||        y w)Nz{0:}=[{1:}],z{0:}="{1:}"\z\\"z\")	sorteditemsr   dictformatjoinr   strreplace)	to_renderkeyr#   itemr   s       r   r   zrender.<locals>.recurse/   s      !23 	3JC}%&#**30HII%&! MD'..sCHHWT]4KLLM%%#**3dF0K0S0STWY^0_``&&sE22	3s   C:C=
)r.   )r1   r   s    @r   renderr5   -   s    3 99WY'((r   c                   ^   e Zd ZdZ e eddg ej                  d             ed ej                  d             eddd	g ej                  d
             edd       edd            Zd%dZd Z	d Z
d Zd Zd Zd Zd Zd Zd Zd Zd Zd Z	 	 d&dZd  Zd! Zd" Zd# Zd$ Zy)'OpenNebulaModulez
    Base class for all OpenNebula Ansible Modules.
    This is basically a wrapper of the common arguments, the pyone client and
    some utility methods.
    r/   api_endpointONE_URL)typealiasesdefaultONE_USERNAME)r:   r<   T	api_tokenONE_PASSWORD)r:   no_logr;   r<   bool)r<   r:   inti,  )api_urlapi_usernameapi_passwordvalidate_certswait_timeoutNc                    t         j                  j                         }|j                  |       t	        |||||      | _        t        ddd      | _        | j                         | _	        | j                         | _        y )N)argument_specsupports_check_modemutually_exclusiverequired_one_ofrequired_ifF )changedoriginal_messagemessage)r7   common_argscopyupdater   moduler,   resultcreate_one_clientoneresolve_parametersresolved_parameters)selfrI   rJ   rK   rL   rM   module_argss          r   __init__zOpenNebulaModule.__init__P   sw    &22779=)#+8K7I4C0;	=
 5,.#%' ))+#'#:#:#< r   c                 B   t        t        d      rt        j                         }nd}t        s| j	                  d       | j
                  j                  j                  d      r&| j
                  j                  j                  d      }n| j	                  d       | j
                  j                  j                  d      r&| j
                  j                  j                  d      }n| j	                  d       | j
                  j                  j                  d      r&| j
                  j                  j                  d      }n| j	                  d	       d
}| j
                  j                  j                  d      sdt        vrt        ||      S t        |      S )zc
        Creates an XMLPRC client to OpenNebula.

        Returns: the new xmlrpc client.

        _create_unverified_contextNz!pyone is required for this modulerC   zCEither api_url or the environment variable ONE_URL must be providedrD   zMEither api_username or the environment variable ONE_USERNAME must be providedrE   zMEither api_password or the environment variable ONE_PASSWORD must be provided:rF   PYTHONHTTPSVERIFY)sessioncontext)
hasattrsslr_   	HAS_PYONEfailrU   paramsgetr   r   )r[   no_ssl_validation_contexturlusernamepasswordrb   s         r   rW   z"OpenNebulaModule.create_one_clienta   s<    345(+(F(F(H%(,% II9:;;!!),++$$((3CII[\;;!!.1{{))--n=HIIef;;!!.1{{))--n=HIIef%x0{{!!%%&67<OW^<^S';TUUS'**r   c                 8    | j                   j                          y)z*
        Close the pyone session.
        N)rX   server_closer[   s    r   close_one_clientz!OpenNebulaModule.close_one_client   s     	r   c                 t    t        | d      r| j                          | j                  j                  |       y)z
        Utility failure method, will ensure pyone is properly closed before failing.
        Args:
            msg: human readable failure reason.
        rX   msgN)rd   rq   rU   	fail_json)r[   rt   s     r   rg   zOpenNebulaModule.fail   s/     4!!##&r   c                     t        | d      r| j                           | j                  j                  di | j                   y)z\
        Utility exit method, will ensure pyone is properly closed before exiting.

        rX   N )rd   rq   rU   	exit_jsonrV   rp   s    r   exitzOpenNebulaModule.exit   s5    
 4!!#,,r   c                 b   t        | j                  j                        }d| j                  j                  v rw| j                  j                  j                         }|j                  D ]D  }|j                  | j                  j                  j                  d      k(  s6|j                  |d<   F |S )a.  
        This method resolves parameters provided by a secondary ID to the primary ID.
        For example if cluster_name is present, cluster_id will be introduced by performing
        the required resolution

        Returns: a copy of the parameters that includes the resolved parameters.

        cluster_name
cluster_id)
r,   rU   rh   rX   clusterpoolinfoCLUSTERNAMEri   ID)r[   resolved_paramsclustersclusters       r   rY   z#OpenNebulaModule.resolve_parameters   s     t{{112T[[///xx++002H#++ ?<<4;;#5#5#9#9.#II4;JJOL1? r   c                 F    || j                   v r| j                  |      duS y)z
        Utility method to check if a parameter was provided or is resolved
        Args:
            name: the parameter to check
        NF)rZ   get_parameterr[   names     r   is_parameterzOpenNebulaModule.is_parameter   s+     4+++%%d+477r   c                 8    | j                   j                  |      S )z
        Utility method for accessing parameters that includes resolved ID
        parameters from provided Name parameters.
        )rZ   ri   r   s     r   r   zOpenNebulaModule.get_parameter   s    
 ''++D11r   c                     | j                   j                  j                         }|j                  D ]  }|j                  |k(  s|c S  y)z
        Returns a host given its name.
        Args:
            name: the name of the host

        Returns: the host object or None if the host is absent.

        N)rX   hostpoolr~   HOSTr   )r[   r   hostshs       r   get_host_by_namez!OpenNebulaModule.get_host_by_name   sD     !!&&( 	Avv~	 r   c                     | j                   j                  j                         }|j                  D ]  }|j                  |k(  s|c S  y)z
        Returns a cluster given its name.
        Args:
            name: the name of the cluster

        Returns: the cluster object or None if the host is absent.
        N)rX   r}   r~   r   r   )r[   r   r   cs       r   get_cluster_by_namez$OpenNebulaModule.get_cluster_by_name   sF     88'',,.!! 	Avv~	 r   c                     | j                   j                  j                         }|j                  D ]  }|j                  |k(  s|c S  y)z
        Returns a template given its name.
        Args:
            name: the name of the template

        Returns: the template object or None if the host is absent.

        N)rX   templatepoolr~   TEMPLATEr   )r[   r   	templatests       r   get_template_by_namez%OpenNebulaModule.get_template_by_name   sF     HH))..0	## 	Avv~	 r   c                     |D ]p  }||   }t        |t              r| j                  ||          -t        |t              rdj	                  |      ||<   Rt        |t
              rct        |      ||<   r y)a  
        OpenNebula handles all template elements as strings
        At some point there is a cast being performed on types provided by the user
        This function mimics that transformation so that required template updates are detected properly
        additionally an array will be converted to a comma separated list,
        which works for labels and hopefully for something more.

        Args:
            template: the template to transform

        Returns: the transformed template with data casts applied.
        z, N)r   r,   cast_templater   r.   r   r/   )r[   templater2   r#   s       r   r   zOpenNebulaModule.cast_template   sk    "  	+CSME%&""8C=1E4( $		% 0|4 #E
	+r   c                     |sy| j                  |       t               }|j                         D ]  }||j                         v r	||   ||<    y ||k(   S )a  
        This function will help decide if a template update is required or not
        If a desired key is missing from the current dictionary an update is required
        If the intersection of both dictionaries is not deep equal, an update is required
        Args:
            current: current template as a dictionary
            desired: desired template as a dictionary

        Returns: True if a template update is required
        FT)r   r,   keys)r[   currentdesiredintersectiondkeys        r   requires_template_updatez)OpenNebulaModule.requires_template_update  sc     7#vLLN 	Dw||~%%,T]T"		
 |+,,r   c                    |s%| j                   j                  j                  d      }t        j                         }t        j                         |z
  |k  r |       }	|	|v r| j	                  d|d ||	             |r!|	|vr| j	                  d|d ||	             |	|v ryt        j
                  | j                  j                                t        j                         |z
  |k  r| j	                  d       y)	aS  
        Args:
            element_name: the name of the object we are waiting for: HOST, VM, etc.
            state: lambda that returns the current state, will be queried until target state is reached
            state_name: lambda that returns the readable form of a given state
            target_states: states expected to be reached
            invalid_states: if any of this states is reached, fail
            transition_states: when used, these are the valid states during the transition.
            wait_timeout: timeout period in seconds. Defaults to the provided parameter.
        rG   zinvalid z state z transition state TzWait timeout has expired!rs   N)rU   rh   ri   timerg   sleeprX   server_retry_interval)
r[   element_namestate
state_nametarget_statesinvalid_statestransition_statesrG   
start_timecurrent_states
             r   wait_for_statezOpenNebulaModule.wait_for_state'  s     ;;--11.ALYY[
yy{Z'<7!GM.		<MAZ[\  (99II,PZ[hPijk-JJtxx5578 yy{Z'<7 			1	2r   c                     	 | j                  | j                  | j                  | j                         y# t        $ r}| j                  d|z         Y d}~yd}~ww xY w)zU
        trigger the start of the execution of the module.
        Returns:

        zOpenNebula Exception: %srs   N)runrX   rU   rV   r   rg   )r[   es     r   
run_modulezOpenNebulaModule.run_moduleK  sJ    	:HHTXXt{{DKK8 	:II4q8I99	:s   14 	AAAc                     t        d      )z
        to be implemented by subclass with the actual module actions.
        Args:
            one: the OpenNebula XMLRPC client
            module: the Ansible Module object
            result: the Ansible result
        zMethod requires implementation)NotImplementedError)r[   rX   rU   rV   s       r   r   zOpenNebulaModule.runV  s     ""BCCr   c                     g }|dk(  r|j                   }|dk(  r|j                  }|dk(  r|j                  }j                  D ]  }|j	                  t        |dd               |S )zg
        This is a helper function for get_image_info to iterate over a simple list of objects
        VMSCLONES
APP_CLONESr   Null)r   r   r   r   appendgetattr)r[   imageelement
list_of_id
image_listiters         r   get_image_list_idz"OpenNebulaModule.get_image_list_id`  ss     
eJhJl"))JMM 	DdF+	
 r   c                     g }|j                   j                  D ]Z  }|j                  |d   |d   |d   t        |j                   dd      t        |dd      t        |dd      t        |dd      d	       \ |S )
z[
        This is a helper function for get_image_info to iterate over a dictionary
        DATEPARENTSIZEALLOW_ORPHANSr   CHILDRENACTIVEr   )dateparentsizeallow_orhanschildrenactiver   )	SNAPSHOTSSNAPSHOTr   r   )r[   r   list_of_snapshotsr   s       r   get_image_snapshots_listz)OpenNebulaModule.get_image_snapshots_listt  s     OO,, 
	D$$Vx.V '& Q#D*f=!$&9ff5	& 	
	 ! r   c                 t   i d|j                   d|j                  dt        |j                     d|j                  dt        |j                        d|j                  d|j                  d|j                  d	|j                  d
|j                  j                  |j                  j                  |j                  j                  |j                  j                  |j                  j                  |j                  j                   |j                  j"                  |j                  j$                  |j                  j&                  d	d|j(                  d|j*                  d|j,                  d|j.                  d|j0                  d|j2                  dt5        |dd      |j6                  |j8                  |j:                  |j<                  |j>                  |j@                  | jC                  |d      | jC                  |d      | jC                  |d      | jE                  |      |jF                  d}|S )z
        This method is used by one_image and one_image_info modules to retrieve
        information from XSD scheme of an image
        Returns: a copy of the parameters that includes the resolved parameters.
        idr   r   running_vmsused	user_nameuser_id
group_namegroup_idpermissions)	owner_uowner_mowner_agroup_ugroup_mgroup_aother_uother_mother_ar:   	disk_type
persistentregtimesourcepathfstypeFSTYPEr   r   r   r   )r   cloning_ops
cloning_idtarget_snapshotdatastore_id	datastorevmsclones
app_clones	snapshotsr   )$r   r   IMAGE_STATESSTATERUNNING_VMSrA   UNAMEUIDGNAMEGIDPERMISSIONSOWNER_UOWNER_MOWNER_AGROUP_UGROUP_MGROUP_AOTHER_UOTHER_MOTHER_ATYPE	DISK_TYPE
PERSISTENTREGTIMESOURCEPATHr   r   CLONING_OPS
CLONING_IDTARGET_SNAPSHOTDATASTORE_ID	DATASTOREr   r   r   )r[   r   r~   s      r   get_image_infozOpenNebulaModule.get_image_info  s7   '
%(('
EJJ'
 \%++.'
 5,,	'

 D**+'
 '
 uyy'
 %++'
 		'
  ,,44 ,,44 ,,44 ,,44 ,,44 ,,44 ,,44 ,,44 ,,44
'
* EJJ+'
, -'
. %**/'
0 u}}1'
2 ell3'
4 EJJ5'
6 geXv67'
8 JJ ,,**$44!..))%7,,UH=00E66u=M'
P r   )FNNN)NNN)__name__
__module____qualname____doc__r,   r   ri   rR   r]   rW   rq   rg   ry   rY   r   r   r   r   r   r   r   r   r   r   r   r   r  rw   r   r   r7   r7   A   s     %.)9;7;;yCYZukgkk..IJuTK=R]RYR]R]^lRmnDv6uc2K="&+P '-(	2+4-2 ?C$("3H	:D(!&.r   r7   )F)
__future__r   r   r   r:   __metaclass__r   re   osr   ansible.module_utils.sixr   ansible.module_utils.basicr   r   rf   pyoner   pyone.serverr   ImportError	Exceptionr$   r5   r7   rw   r   r   <module>r!     sn    C B  
  1 4 K	"&)(t tQ  LIs   A 	AA