B
    `R                 @   s  d dl Z d dlZd dlZd dlZd dlZd dlmZmZ d dlm	Z	 d dl
mZmZmZ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 d dlmZ d dlmZ d d	lmZ  e!e"Z#e j$G d
d deZ%G dd deZ&e j$G dd deZ'dd Z(e j$G dd deZ)e j$G dd de)Z*e j$G dd de)Z+G dd de)Z,G dd deZ-G dd deZ.dd Z/d d! Z0e	d"d#d$ed%d& Z1dS )'    N)BooleanFieldStringField)view_config)UploadEngineNoTransactionEngineUserInitialPost
UserWTFormCredsLoadedFormSessionDBHandlerLogSQLCommandSQLDataNoOpProcessor
ExecuteSQLformat_exception)AuthFailError)CHECKED	UNCHECKED)errors_base_view)utils)
exceptionsc                   sT   e Zd ZdZejddZejddZejddZejddZ	i f fdd	Z
  ZS )CopySchemaInitialPostzOGet values from settings when there's not user-supplied values
    in POST
    N)defaultFc                s:   t  | |d d }|d | _|d | _|d | _| S )Npgwui
pgwui_copyZdefault_schemaZdefault_source_dbZdefault_target_db)superbuildschemafrom_dbto_db)selfsettingsZcopy_settings)	__class__ ]/home/kop/projects/devel/pgwui/test_venv/lib/python3.7/site-packages/pgwui_copy/views/copy.pyr   L   s    


zCopySchemaInitialPost.build)__name__
__module____qualname____doc__attribr   r   r   forcer   __classcell__r"   r"   )r!   r#   r   B   s   r   c               @   s8   e Zd ZdZedZedZedZedZ	edZ
dS )CopySchemaWTFormz@The wtform used to connect to the "gombemi" db to authenticate .zSchema To Copy:zFrom Database:zTo Database:zOverwrite Destination Schema:zAllow Copy To Sensitive DBs:N)r$   r%   r&   r'   r   r   r   r   r   	overwriter*   r"   r"   r"   r#   r,   V   s   r,   c                   s,   e Zd ZdZ fddZ fddZ  ZS )CopySchemaFormz|
    Acts like a dict, but with extra methods.

    Attributes:
      uh      The UploadHandler instance using the form
    c                sl   t    | jjj  | d< | jjj  | d< | jjj  | d< | jj	j| d< | jj
j| d< dS )z0
        Read form data from the client
        r   r   r   r-   r*   N)r   readZ_formr   datalowerstripr   r   r-   r*   )r   )r!   r"   r#   r/   j   s    
zCopySchemaForm.readc                sj   t  ||}| d |d< | d |d< | d |d< | d r@t}nt}||d< | d rZt}nt}||d< |S )zH
        Produces the dict pyramid will use to render the form.
        r   r   r   r*   r-   )r   writer   r   )r   resulterrorsresponseZforce_checkedZoverwrite_checked)r!   r"   r#   r3   y   s    zCopySchemaForm.write)r$   r%   r&   r'   r/   r3   r+   r"   r"   )r!   r#   r.   b   s   r.   c             C   s   |  d|f |  dk	S )zDoes the schema exist?z.SELECT 1 FROM pg_namespace  WHERE nspname = %sN)executefetchone)curr   r"   r"   r#   schema_exists   s    r:   c                   sT   e Zd ZdZdd Z fddZdd Z fdd	Zd
d Zdd Z	dd Z
  ZS )CopySchemaHandlerzA
    Abstract class to copy a schema from one db to another.
    c             C   s   t  j| tt dS )N)Zfcip)r.   r   r,   r   )r   r"   r"   r#   	make_form   s    zCopySchemaHandler.make_formc                s.   t  ||}|d  o$| jd dk|d< |S )a  
        Setup dict to render resulting html form

        Returns:
          Dict pyramid will use to render the resulting form
          Reserved keys:
            errors      A list of UploadError exceptions.
            db_changed  Boolean. Whether the db was changed.
        r5   action 
db_changed)r   r3   uf)r   r4   r5   r6   )r!   r"   r#   r3      s    

zCopySchemaHandler.writec             C   s
   t || S )zrMake a db loader function from an UploadEngine.

        Input:

        Side Effects:
        Yes, lots.
        )r   )r   uer"   r"   r#   factory   s    zCopySchemaHandler.factoryc                s   t  ||}||fS )zInstead of rendering, just our results so we can
        decide what to do next.

        Input:
          errors    List of Error instances
          result    Db connection result dict
        )r   render)r   r5   r4   r6   )r!   r"   r#   rD      s    zCopySchemaHandler.renderc             C   s   dj | jd | jd dS )z?Return a string for the log detailing an SQL execution attempt.z"In database {db}: By user ({user})r   user)dbrE   )formatrA   )r   r"   r"   r#   to_db_detail   s    zCopySchemaHandler.to_db_detailc             C   s   t d||   dS )z6Write a success message to the log when executing sql.z{0}: {1}N)logwarningrG   rH   )r   msgr"   r"   r#   log_sql_success   s    z!CopySchemaHandler.log_sql_successc             C   s    t d||  t| dS )z7Write a failture message to the log when executing sql.z{0}: {1}{2}N)rI   inforG   rH   r   )r   rK   exr"   r"   r#   log_sql_failure   s    z!CopySchemaHandler.log_sql_failure)r$   r%   r&   r'   r=   r3   rC   rD   rH   rL   rO   r+   r"   r"   )r!   r#   r;      s   
r;   c                   sH   e Zd ZdZejddZ fddZ fddZdd	 Z	d
d Z
  ZS )FromSchemaHandlerz^Handler to check the source schema and do initial validation.

    Attributes:
       cur
    N)r   c                s   t    | jjj| _d S )N)r   initrequestregistryr    )r   )r!   r"   r#   rQ      s    
zFromSchemaHandler.initc                s   |j | _ | j}| j }|d }|d|f | dkrXtdd|}| d| ||d }t||st	dd	|}| d| |t
 |S )
zMake a db loader function from an UploadEngine.
        Having the UploadEngine we can test the db content.

        Input:

        Side Effects:
        Yes, lots.
        rE   z7SELECT 1 FROM pg_roles  WHERE rolname = %s AND rolsuperNzMust be a superuserz/The supplied user ({0}) is not an administratorzUser not a superuserr   zSource schema does not existz/The supplied source schema ({0}) does not exist)r9   rA   r7   r8   copy_exZNonAdminUserErrorrG   rO   r:   ZInvalidSchemaErrorr   rC   )r   rB   rA   r9   rE   rN   r   )r!   r"   r#   rC      s,    	
zFromSchemaHandler.factoryc             C   s
   d| _ dS )z4We do all the work validating input so need no data.r"   N)r0   )r   r"   r"   r#   get_data  s    zFromSchemaHandler.get_datac          	   C   s@  | j }g }|d }|dkr:td}| d| || | jd d d }|d dkrztd}| d| || nP|d  |kr|d	 std
d	|d }| d|d  d| || |d dkrt
d}| d| || nD|d |d kr<tdd	t|d }| d| || |S )z
        Validate input needed beyond that required to connect to the db.

        Returns:
          A list of Error instances
        r   r?   zNo schema suppliedr   r   sensitive_dbsr   zNo to db suppliedr*   z&Cannot write into a sensitive databasezDThe "Allow ..." box must be checked to copy into the "{0}" database.z>Aborted: The "Allow..." box must be checked to copy into the "z
" databaser   zNo from db suppliedz$The from db is the same as the to dbz)Both the from db and the to db are ({0}).zFrom db and to db are the same)rA   rT   ZNoSchemaErrorrO   appendr    ZNoToDBErrorr1   ZLiveDBTargetErrorrG   ZNoFromDBErrorZSameDBError
markupsafeescape)r   rA   r5   r   rN   rV   r"   r"   r#   	val_input  sB    





zFromSchemaHandler.val_input)r$   r%   r&   r'   r(   r)   r    rQ   rC   rU   rZ   r+   r"   r"   )r!   r#   rP      s   &rP   c                   sT   e Zd ZdZejddZ fddZdd Zdd	 Z	d
d Z
dd Zdd Z  ZS )DropSchemaHandlerz
    Handler to drop the target schema from the target db.

    (Extra) Attributes:
      drop_attempted  True when the handler will attempt to drop the
                      schema.
    F)r   c                s   |j }| jd }t||rp| jd r6d| _t |S td|| jd  t	
ddt|| jd n"td|| jd  t|| S d	S )
zMake a db loader function from an UploadEngine.
        Having the UploadEngine we can test the db content.

        Input:

        Side Effects:
        Yes, lots.
        r   r-   Tz2Abort: Schema ({0}) already exists in the ({1}) dbr   zThe target schema existsz&The schema ({0}) exists in the {1} db.z+Schema ({0}) does not exist in the ({1}) dbN)r9   rA   r:   drop_attemptedr   rC   rI   rM   rG   rT   ZSchemaExistsErrorrX   rY   r   )r   rB   r9   r   )r!   r"   r#   rC   N  s    	


zDropSchemaHandler.factoryc             C   s   |  d| jd  dS )z<Write a success message to the log when dropping the schema.zSuccess dropping schema ({0})r   N)rL   rG   rA   )r   r"   r"   r#   log_dropschema_successj  s    z(DropSchemaHandler.log_dropschema_successc             C   s   |  d| jd | dS )z<Write a failure message to the log when dropping the schema.zFailure dropping schema ({0})r   N)rO   rG   rA   )r   rN   r"   r"   r#   log_dropschema_failureo  s    
z(DropSchemaHandler.log_dropschema_failurec             C   s   |  d dS )z=Write a success message to the log when vacuum full succeeds.zSuccessful VACUUM FULLN)rL   )r   r"   r"   r#   log_vacuumfull_successu  s    z(DropSchemaHandler.log_vacuumfull_successc             C   s   |  d| dS )z:Write a failure message to the log when vacuum full fails.zFailed VACUUM FULLN)rO   )r   rN   r"   r"   r#   log_vacuumfull_failurey  s    z(DropSchemaHandler.log_vacuumfull_failurec          	      sx   | j }g }|d  |d |td d fdd| j| jd |tddfd	d| j| jd t|| _	d
S )zq
        Build and stash the SQL to be executed.

        Returns:
          List of SQCommand instances
        r   r   zDROP SCHEMA {0} CASCADEr"   c                s   t |  S )N)rT   ZDropSchemaError)rN   )r   r   r"   r#   <lambda>      z,DropSchemaHandler.get_data.<locals>.<lambda>)log_successlog_failurezVACUUM FULLc                s   t |  S )N)rT   ZVacuumFullError)rN   )r   r"   r#   ra     rb   N)
rA   rW   r   rG   r]   r^   r_   r`   r   r0   )r   rA   sqlr"   )r   r   r#   rU   }  s"    
zDropSchemaHandler.get_data)r$   r%   r&   r'   r(   r)   r\   rC   r]   r^   r_   r`   rU   r+   r"   r"   )r!   r#   r[   C  s   r[   c               @   s(   e Zd ZdZdd Zdd Zdd ZdS )	VacuumHandlerz6
    Handler to add a user schema to the test db.
    c             C   s   |  d d S )NzSuccessful VACUUM ANALYZE)rL   )r   r"   r"   r#   log_vacuumanalyze_success  s    z'VacuumHandler.log_vacuumanalyze_successc             C   s   |  d| d S )NzFailed VACUUM ANALYZE)rO   )r   rN   r"   r"   r#   log_vacuumanalyze_failure  s    z'VacuumHandler.log_vacuumanalyze_failurec          	      sD   | j }g }|d  |tdd fdd| j| jd t|| _dS )zq
        Build and stash the SQL to be executed.

        Returns:
          List of SQCommand instances
        r   zVACUUM ANALYZEr"   c                s   t |  S )N)rT   ZVacuumAnalyzeError)rN   )r   r"   r#   ra     rb   z(VacuumHandler.get_data.<locals>.<lambda>)rc   rd   N)rA   rW   r   rg   rh   r   r0   )r   rA   re   r"   )r   r#   rU     s    
zVacuumHandler.get_dataN)r$   r%   r&   r'   rg   rh   rU   r"   r"   r"   r#   rf     s   rf   c                   s(   e Zd ZdZ fddZdd Z  ZS )CheckFromSchemaEnginez+Customize credential failure error message.c                s$   t   }td| jjd |jS )NzUnable to login to the ({0}) dbr   )r   authfailerror_factoryr   rG   uhrA   descr)r   orig)r!   r"   r#   rj     s
    
z+CheckFromSchemaEngine.authfailerror_factoryc             C   s   | j jd | _dS )z-The handler has two db's, save the right one.r   N)rk   rA   rF   )r   r"   r"   r#   read_db  s    zCheckFromSchemaEngine.read_db)r$   r%   r&   r'   rj   rn   r+   r"   r"   )r!   r#   ri     s   ri   c               @   s   e Zd ZdZdd ZdS )
ToDBEnginezUse the to_db to login.c             C   s   | j jd | _d S )Nr   )rk   rA   rF   )r   r"   r"   r#   rn     s    zToDBEngine.read_dbN)r$   r%   r&   r'   rn   r"   r"   r"   r#   ro     s   ro   c          
   C   s^  |d }|d }|d d }| d }| d }| d }| d }| d	 }	t jd
dd}
|
j}|
dj|||||d |
  d|||	|}y<tjd|dddddd|df	dd|ddtjtjd}W nD t	k
r
 } z$t
d||j td|W dd}~X Y nX y4tjd|d dd!|	fdd|d	d|jtjd"}W nD t	k
r } z$t
d#||j td$|W dd}~X Y nX t| d% jd&d'}t| d% jd&d'}|j}|rt
d(| d)t| d)|  td*| d+|||j}|rBt
d,| d)t| d)|  td-|	 d+||t
d.| |
  dS )/a9  Copy the desired schema using pg_dump/pg_restore.

    Input:
      uf        The upload form, holding some of the info we need
                to do the copy.
      settings  The configuration settings, holding some of the info we need
                to do the copy.

    Returns:
      Exception, or None.
    Zpg_hostZpg_portr   binrE   passwordr   r   r   wZcopy_schema_service_file)modeprefixz[from_db]
host={host}
port={port}
dbname={from_db}
user={user}
password={password}

[to_db]
host={host}
port={port}
user={user}
password={password}
)r   rE   rq   hostportz4User ({0}): From db ({1}): To db ({2}): Schema ({3})z{0}/pg_dumpz--formatcz
--compress0z--no-passwordz--schemaz--blobsT)ZPGSERVICEFILEZ	PGSERVICE)bufsize	close_fdsenvstdoutstderrz4Failed to execute pg_dump command: {0}: OS error {1}z!Failed to execute pg_dump commandNz{0}/pg_restorez--single-transactionz--dbname)rz   r{   r|   stdinr~   z7Failed to execute pg_restore command: {0}: OS error {1}z$Failed to execute pg_restore command   backslashreplace)r5   zpg_dump process failed: z: z-Failure of pg_dump process to dump into the "z
" databasezpg_restore process failed: z3Failure of pg_restore process to restore into the "zSuccessfully copied schema: {0})tempfileNamedTemporaryFilename
writelinesrG   flush
subprocessPopenPIPEOSErrorrI   warnstrerrorrT   ZPGDumpOSErrorr}   ZPGRestoreOSErrorrX   rY   communicatedecode
returncoder   Ztranslate_retcodeZPGDumpErrorZPGRestoreErrorclose)rA   r    ru   rv   rp   rE   rq   r   r   r   sfileZservicefileZlog_infoZpg_dumprN   Z
pg_restoreZrestore_errorsZdump_errorsZdump_retcodeZrestore_retcoder"   r"   r#   copy_schema  s    
"
"
r   c             C   s   |d | d< | S )Nr   r"   )r6   r    r"   r"   r#   	add_pgwuiF  s    r   r   zpgwui_copy:templates/copy.mak)Z
route_nameZrendererc             C   s  | j }d|ko|d dk}|r(td t| }|  t| \}}| jj}|rhtd t	||S t
| }|  t| \}}|d ryt|j|d  W n| tjk
r" } zZ|g}	|jr|	tddjt|jd	 t|jd
 d |d |	 d|d< W d d }~X Y nX t|jd	 }
t|jd
 }t|jd }t|jd }td|
 d| d| d|  t| }|  t| \}}|r|tdd| d |d | |d= ntd|  || |rtd t	||S )Nr>   r?   zProcessing form submissionzFailed feasiblity testr@   r   z%Target schema dropped but copy failedzqThe ({schema}) schema was dropped from the {db} db but the copy failed so now it no longer exists in the {db} db.r   r   )r   rF   r5   Fr   rE   z$Successfully copied schema: Schema (z): From DB (z
): To DB (z): By user zVACUUM ANALYZE failedzVACUUM ANALYZE failed in the z db, performance may sufferzVacuum analyzed zFinished processing request)POSTrI   debugrP   rQ   ri   runrS   r    r   r[   ro   r   rA   rT   ZCopyCommandErrorr\   rW   ZSchemaDroppedErrorrG   rX   rY   extendrM   rf   ZSchemaCopiedErrorupdate)rR   postZform_submittedZfrom_handlerr6   r5   r    Zdrop_handlerrN   Z
copyerrorsr   r   r   rE   Zvacuum_handlerZ	vacuumoutZvacuumerrorsr"   r"   r#   copy_schema_viewK  s^    




"

r   )2r(   loggingr   r   rX   Zwtformsr   r   Zpyramid.viewr   Zpgwui_core.corer   r   r   r   r	   r
   r   r   r   r   r   Zpgwui_core.exceptionsr   Zpgwui_core.constantsr   r   Zpgwui_common.viewr   r   r   r   rT   	getLoggerr$   rI   sr   r,   r.   r:   r;   rP   r[   rf   ri   ro   r   r   r   r"   r"   r"   r#   <module>   sB   4
1?fY"s