
    !j$&                    R   d Z ddlmZ 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
 ddlZ e ee      j                         j                  j                  dz  dz        ZdZd	Zd
Zd Z	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZddZd dZd!dZd"dZd#dZd$dZd%dZ	 	 d&	 	 	 	 	 	 	 d'dZ	 	 d&	 	 	 	 	 	 	 	 	 d(dZedk(  rn e ejB                        dk  r& e"dejF                          ejH                  d        eejB                  d   djK                  ejB                  dd              yy))u  SSH-команды на хостах девайсов.

Учётные данные лежат в отдельной БД `ssh_hosts.db`:
имя девайса, IP, пароль, логин (по умолчанию `root`), порт сервера (по умолчанию `22`).
    )annotationsN)Path)Optionaldatabasezssh_hosts.dbroot      c                    t        t              j                  j                  dd       t	        j
                  t              } t        j                  | _        | j                         }|j                  d       |j                  d       |j                         D ch c]  }|d   	 }}d|vr|j                  d       d|vr|j                  d	       | j                          | S c c}w )
NT)parentsexist_okz
        CREATE TABLE IF NOT EXISTS ssh_hosts (
            device TEXT PRIMARY KEY,
            ip TEXT NOT NULL,
            password TEXT,
            username TEXT DEFAULT 'root',
            port INTEGER DEFAULT 22
        )
        zPRAGMA table_info(ssh_hosts)   usernamez=ALTER TABLE ssh_hosts ADD COLUMN username TEXT DEFAULT 'root'portz8ALTER TABLE ssh_hosts ADD COLUMN port INTEGER DEFAULT 22)r   DB_PATHparentmkdirsqlite3connectRowrow_factorycursorexecutefetchallcommit)conncurrowcolss       //var/www/oz-panel.ru/ozpay-pub/utils/ssh_cmd.pyget_connr       s    Mtd;??7#D{{D
++-CKK	
 KK./!lln-sCF-D-STTNOKKMK .s   C'c                z   | xs dj                         } |xs dj                         }| st        d      |st        d      t        |       }|dv r"|st        d      |j                  d      xs d}|s|xs i j                  d      xs t        }|dv r|xs i j                  d      xs t
        }	 t        |      }t               }|j                         }|j                  d
| |||xs t        |f       |j                          |j                          y # t        t        f$ r}t        d	      |d }~ww xY w)N ,   Имя девайса обязательноu   IP обязателен)Nr"   u%   Пароль SSH обязателенpasswordr   r   u:   Порт сервера должен быть числомa*  
        INSERT INTO ssh_hosts (device, ip, password, username, port)
        VALUES (?, ?, ?, ?, ?)
        ON CONFLICT(device) DO UPDATE SET
            ip = excluded.ip,
            password = excluded.password,
            username = excluded.username,
            port = excluded.port
        )strip
ValueErrorget_hostgetDEFAULT_USERDEFAULT_PORTint	TypeErrorr    r   r   r   close)	deviceipr$   r   r   existingexcr   r   s	            r   upsert_hostr2   2   s<    l!!#F
(			BGHH233H:DEE<<
+1rN''
3C|zB##F+;|`4y :D
++-CKK	 
Xx7<> 	KKMJJL# z" `UV\__`s   5D D:)D55D:c                    t               }|j                         }|j                  d| f       |j                         }|j	                          |sy t        |      S )Nz(SELECT * FROM ssh_hosts WHERE device = ?)r    r   r   fetchoner-   dict)r.   r   r   r   s       r   r'   r'   ^   sI    :D
++-CKK:VIF
,,.CJJL9    c                     t               } | j                         }|j                  d       |j                         }| j	                          |D cg c]  }t        |       c}S c c}w )NzSELECT * FROM ssh_hosts)r    r   r   r   r-   r5   )r   r   rowsrs       r   
list_hostsr:   i   sM    :D
++-CKK)*<<>DJJL!"DG"""s   A%c                    t               }|j                         }|j                  d| f       |j                          |j                  }|j                          |dkD  S )Nz&DELETE FROM ssh_hosts WHERE device = ?r   )r    r   r   r   rowcountr-   )r.   r   r   changeds       r   delete_hostr>   r   sJ    :D
++-CKK86)DKKMllGJJLQ;r6   c                   | xs dj                         } |xs dj                         }| r|r| |k(  ryt               }|j                         }	 |j                  d|| f       |j	                          |j
                  }|j                          |dkD  S # t        j                  $ r%}|j                          t        d| d      |d }~ww xY w)Nr"   Fz0UPDATE ssh_hosts SET device = ? WHERE device = ?u   SSH-запись 'u   ' уже естьr   )
r%   r    r   r   r   r<   r   IntegrityErrorr-   r&   )oldnewr   r   r=   r1   s         r   rename_hostrC   |   s    9"


C9"


CcSCZ:D
++-COFc
S,, 	JJLQ;	 !! O

-cU2CDE3NOs   0B C& CCc                   | g S t        | t              r| j                         }n	 t        |       }|D cg c]5  }t        |      j                         st        |      j                         7 c}S # t        $ r | g}Y Ow xY wc c}w )N)
isinstancestr
splitlineslistr,   r%   )commandsitemsitems      r   _normalize_commandsrL      sx    	(C ##%	NE +0E$3t9??3DCIOOEE  	JE	Es   A3 BB3BBc                   | xs dj                         } | st        d      t        |       }|st        d|  d      |j	                  d      xs dj                         }|st        d|  d      |j	                  d      xs t
        j                         xs t
        }	 t        |j	                  d	      xs t              }|j	                  d
      xs d}t        j                         }|j                  t        j                                |j                  ||||t        t        t        dd	       |||fS # t        t        f$ r	 t        }Y w xY w)Nr"   r#   u$   SSH-хост для девайса 'u#   ' не найден в ssh_hosts.dbr/   u   У девайса 'u&   ' не указан IP в ssh_hosts.dbr   r   r$   F)	hostnamer   r   r$   timeoutbanner_timeoutauth_timeoutallow_agentlook_for_keys)r%   r&   r'   RuntimeErrorr(   r)   r+   r*   r,   paramiko	SSHClientset_missing_host_key_policyAutoAddPolicyr   CONNECT_TIMEOUT)device_namehostr/   r   r   r$   clients          r   _connect_hostr]      sI   $"++-KGHHK DA+Nqrss
((4.
B	%	%	'B0=cdee$4;;=MH488F#3|4 xx
#)rH!F
&&x'='='?@
NN&$  
 2t# z" s   ""D; ;EEc                   t        j                  dt        j                  |       d      }d gt        |      z  }d}|j	                  |       D ]  }t        |j                  d            }t        |j                  d            }	| ||j                          }
|j                         }|
j                  d      r|
dd  }
|
j                  d      r|
d d }
d|cxk  rt        |      k  sn ||   ||   |
d|	d	||<    | |d  }d
}t        |      D ]&  \  }}||   ||r|ndd|r|nd | d||<   |s#d}d}( |D cg c]  }||	 c}S c c}w )N__OZPAY_z__:(\d+):(\d+)__r   r      
r"   )commandstdoutstderr	exit_codeT)rc   rd   re   rf   skippedF)recompileescapelenfinditerr+   groupstartend
startswithendswith	enumerate)texttokenrI   
shell_exitpatternresultsposmatchidxcodechunktailfirst_missingirc   rK   s                   r   _parse_session_outputr      s   jjHRYYu%5$66FGHG%)FS]$:G
C!!$' %++a.!5;;q>"S'iikD!!"IE>>$#2JE#c(m#(<#C=!	GCL  :DM) "
71:!+d'4$((

 D!M" %9T(8D999s   E	Ec                   | xs dj                         } t        |      }|st        d      t        j                         j
                  }d|dd  }dg}t        |      D ]E  \  }}	|j                  |	       |j                  | d       |j                  d| d	| d
| d       G dj                  |      dz   }
t        |       \  }}}	 |j                  d|      \  }}}|j                  |
       |j                          |j                  j                          |j                         j!                  dd      }|j                         j!                  dd      }|j                  j#                         }|j%                          t'        ||||      }|r"|r |d   }|j)                  d      xs d|z   |d<   |r|D ]  }t+        d|d           |j)                  d      xs d}|r t+        ||j-                  d      rdnd       |j)                  d      xs d}|r/t+        ||j-                  d      rdndt.        j0                         |j)                  d      rt+        d       t+        d|j)                  d               |r|d   j)                  d      n|}t+        d|  d| d| d t3        |       d!| 
       |S # |j%                          w xY w)"u|   Выполнить команды в одной SSH-сессии (общий cwd, переменные, окружение).r"   u%   Команда обязательна__ozpay_st_N   z	exec 2>&1z=$?zprintf "\n__OZPAY_z__:%s:%s__\n" "z" "${z}"ra   z
/bin/sh -s)rO   zutf-8replace)errorsrb   re   z$ rc   rd   )ro   )ro   filerg   z[ssh] skippedz[ssh] exit=rf   z[ssh] @:z cmds=z exit=)r%   rL   r&   uuiduuid4hexrr   appendjoinr]   exec_commandwriteflushchannelshutdown_writereaddecoderecv_exit_statusr-   r   r(   printrq   sysre   rk   )rZ   rI   rO   echocommand_listrt   
status_varscript_linesindexrc   scriptr\   r/   r   stdinrd   re   outerrru   rw   lastrK   rs   extra	last_codes                             r   run_ssh_commandsr      s    $"++-K&x0L@AAJJLEuRayk*J=L#L1 
wG$zl#./!%(8vj\QTU	

 YY|$t+F$[1FB	 & 3 3L' 3 RvvF$$&kkm""79"=kkm""79"=^^446
#CjIG
wr{((8,2c9X 	=DBtI'()88H%+DddmmD&9tDHHX&,"Eeu~~d';CJJWxx	"o&DHH[$9#:;<	= 18,ZI	F;-qAdV6#l2C1DF9+
VWN/ 	s   B.K Kc                ,    t        | |g||      }|d   S )u   Выполнить команду по SSH на хосте девайса.

    Returns:
        dict с ключами stdout, stderr, exit_code.
    )rO   r   r   )r   )rZ   rc   rO   r   rw   s        r   run_ssh_commandr      s      {WIwTRG1:r6   __main__   z$usage: ssh_cmd.py <device> <command>)r   r`   r    )NNN)r.   rF   r/   rF   r$   Optional[str]r   r   r   zOptional[int]returnNone)r.   rF   r   zOptional[dict])r   
list[dict])r.   rF   r   bool)rA   rF   rB   rF   r   r   )r   	list[str])rZ   rF   r   z#tuple[paramiko.SSHClient, str, int])
rs   rF   rt   rF   rI   r   ru   r+   r   r   )NT)rZ   rF   rO   Optional[float]r   r   r   r   )
rZ   rF   rc   rF   rO   r   r   r   r   r5   )&__doc__
__future__r   rh   r   r   r   pathlibr   typingr   rU   rF   __file__resolver   r   r)   r*   rY   r    r2   r'   r:   r>   rC   rL   r]   r   r   r   __name__rk   argvr   re   exitr    r6   r   <module>r      s   # 	  
    
d8n$$&--44zANR
S: #"))) ) 	)
 ) 
)X#$
F!H#:R  $	88 8 	8
 8|  $	  	
 
 z
388}q43::FCHHQK#((12,!78	 r6   