Console OpenVPN, développée en Django Permet de gérer des instances, serveurs, et comptes OpenVPN
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
8.4 KiB

# -*- coding: utf-8 -*-
#
# vim:syntax=python:sw=4:ts=4:expandtab
# synctools.py
#
# Copyright (C) Adelux - 2009
#
"""
OpenVPNConsole synctools module :
Synchronisation tools used to copy openvpn configuration to non-local servers
"""
import os
import subprocess
import paramiko
import traceback
import sys
import re
class OVPNServerSync:
""" Object used to manage distant server
Sets some default values
"""
def __init__(self, hostname, login, password, port=22):
""" construct object properties """
self.hostname = hostname
self.login = login
self.password = password
self.dst_dir = '/tmp/test_copy'
self.copy_method = 'ssh'
self.source_dir = None
self.port = port
self.ssh_handle = None
def sync(self):
""" connects to server, and copy files """
# if source_dir is not set, returns
if self.source_dir is None:
raise SourceDirError("Source dir %s not defined" % self.source_dir)
# if source_dir does not exist, return
if not os.path.exists(self.source_dir):
raise SourceDirError("Source dir %s does not exist" % self.source_dir)
# create connection
return self._copy_source(self.copy_method)
# Private methods
def _copy_source(self, method):
""" copy files to server, depending on method """
output = ''
if self.copy_method is 'ssh':
# get host key
hostkeytype = None
hostkey = None
try:
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
try:
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
except IOError:
#output += '*** Unable to open host keys file, continuing anyway\n'
host_keys = {}
# try to connect by ssh and use paramiko Transport to negotiate SSH2 across the connection
try:
t = paramiko.Transport((self.hostname, self.port))
t.connect(username=self.login, password=self.password, hostkey=hostkey)
sftp = paramiko.SFTPClient.from_transport(t)
# copy directory onto the server
# go into source_dir and walk in each subdirectory
pwd = os.getcwd()
os.chdir(self.source_dir)
# try to create dst_dir
try:
output += 'creating directory %s \n' % self.dst_dir
sftp.mkdir(self.dst_dir)
except IOError:
output += '(assuming %s already exists) \n' % self.dst_dir
for (root, dirs, files) in os.walk('.'):
# if dirs not empty, create sub directory
if dirs is not None:
for dir in dirs:
dst = os.path.normpath(os.path.join(self.dst_dir, root, dir))
try:
output += 'creating directory %s \n' % dst
sftp.mkdir(dst)
except IOError:
output += '(assuming %s already exists) \n' % dst
# copy each file in distant directory
if files is not None:
for file in files:
src = os.path.normpath(os.path.join(root, file))
dst = os.path.normpath(os.path.join(self.dst_dir, root, file))
try:
output += 'copying file %s to %s \n' % (src, dst)
sftp.put(src, dst)
except IOError:
output += '(error during copy) \n'
t.close()
# change the path again
os.chdir(pwd)
except Exception, e:
output += '*** Caught exception: %s: %s' % (e.__class__, e)
traceback.print_exc()
try:
t.close()
except:
pass
sys.exit(1)
else:
raise ConnectionError("Method %s is not supported by module" % self.copy_method)
output += 'Finished \n'
return output
def __del__(self):
pass
class OVPNServerAdmin:
"""
allows start, stop, restart, reload, status functions to manage local or distant openvpn server
"""
def __init__(self):
self.server_type = 'local'
self.init_script = '/etc/init.d/openvpn'
self.hostname = 'localhost'
self.login = 'user'
self.password = 'password'
self.cmd_prefix = None
# public methods
def start_server(self):
"""
function returns three values : return code, stdout, and sterr
"""
if self.cmd_prefix is not None:
(retcmd, stdout, stderr) = self._shell_cmd(self.cmd_prefix + ' ' + self.init_script + ' ' + 'start', self.server_type)
else:
(retcmd, stdout, stderr) = self._shell_cmd(self.init_script + ' ' + 'start', self.server_type)
output = []
output.append(str(retcmd))
output.append(''.join(stdout) + '\n')
output.append(''.join(stderr) + '\n')
return output
def stop_server(self):
"""
function returns three values : return code, stdout, and sterr
"""
if self.cmd_prefix is not None:
(retcmd, stdout, stderr) = self._shell_cmd(self.cmd_prefix + ' ' + self.init_script + ' ' + 'stop', self.server_type)
else:
(retcmd, stdout, stderr) = self._shell_cmd(self.init_script + ' ' + 'stop', self.server_type)
output = []
output.append(str(retcmd))
output.append(''.join(stdout) + '\n')
output.append(''.join(stderr) + '\n')
return output
def restart_server(self, server_name = ''):
"""
function returns three values : return code, stdout, and sterr
"""
if self.cmd_prefix is not None:
(retcmd, stdout, stderr) = self._shell_cmd(self.cmd_prefix + ' ' + self.init_script + ' ' + 'restart ' + server_name, self.server_type)
else:
(retcmd, stdout, stderr) = self._shell_cmd(self.init_script + ' ' + 'restart ' + server_name, self.server_type)
output = []
output.append(str(retcmd))
output.append(''.join(stdout) + '\n')
output.append(''.join(stderr) + '\n')
return output
def reload_server(self):
"""
function returns three values : return code, stdout, and sterr
"""
if self.cmd_prefix is not None:
(retcmd, stdout, stderr) = self._shell_cmd(self.cmd_prefix + ' ' + self.init_script + ' ' + 'reload', self.server_type)
else:
(retcmd, stdout, stderr) = self._shell_cmd(self.init_script + ' ' + 'reload', self.server_type)
output = []
output.append(str(retcmd))
output.append(''.join(stdout) + '\n')
output.append(''.join(stderr) + '\n')
return output
def get_connected_users(self,status_file):
"""
function returns three values : return code, stdout, and sterr
"""
if self.cmd_prefix is not None:
(retcmd, stdout, stderr) = self._shell_cmd(self.cmd_prefix + 'cat ' + status_file, self.server_type)
else:
(retcmd, stdout, stderr) = self._shell_cmd('cat ' + status_file, self.server_type)
user_list = []
if retcmd == 0 and stdout is not None :
for line in stdout:
p = re.search("^CLIENT_LIST,([^,]*),([^,]*),([^,]*),([^,]*),([^,]*),([^,]*)",line)
if p is not None:
user_list.append(p.group(1,2,3,4,5,6))
return retcmd, user_list, stderr
def get_server_status(self,status_file):
pass
# private methods
def _shell_cmd(self, cmd, connexion):
"""
send 'cmd' shell command to local or distant shell
function returns three values : return code, stdout, and sterr
if access_type is 'ssh', the method needs an additional parameter : ssh connexion object to interract with distant system
"""
if connexion is 'local':
proc = subprocess.Popen(cmd, shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
stdout_value, stderr_value = proc.communicate()
return (proc.returncode, stdout_value, stderr_value)
elif connexion is 'ssh':
# get host key
hostkeytype = None
hostkey = None
# create paramiko object
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy())
# connect to ssh server
ssh.connect(self.hostname, username=self.login, password=self.password)
# execute command
stdin, stdout, stderr = ssh.exec_command(cmd)
output = stdout.readlines()
err = stderr.readlines()
if err:
retcode = -1
else:
retcode = 0
# close connexion
ssh.close()
return (retcode, output, err)
## Additional functions
class SourceDirError(Exception):
pass
class ConnectionError(Exception):
pass