How do I send Server Log to Client through http.server Python? - python

As the question, I now creating a simple http.server with Python and I have to send information about request like Client IP, login time of client, method GET/POST, HTTP header, HTTP body to Client and display it on Frontend. But I don't know how to send and how to get that information to send ? Please help me, thanks
This is my server code:
from http.server import BaseHTTPRequestHandler, HTTPServer
import os
import cgi
from supervisor.medusa.auth_handler import get_header
from database.db import create_table, signup, check_login
from random import randint
from datetime import datetime
import logging
islogin = False
def read_html_template(path):
try:
with open(path) as f:
file = f.read()
except Exception as e:
file = e
return file
class handler(BaseHTTPRequestHandler):
def gen_token(self):
return "".join(str(randint(1, 9)) for _ in range(25))
def get_Ip_addr(self):
return self.client_address[0]
def get_header(self):
return logging.error(self.headers)
def get_time(self):
now = datetime.now()
return now.strftime("%d/%m/%Y %H:%M:%S")
def data_to_send(self):
login_time = self.get_time()
header_data = self.get_header()
ip_client = self.get_Ip_addr()
data = ('{"IP_Client": '+ str(ip_client) + ', "HTTP_Header": ' + str(header_data) + ', "Login_Time": '+ str(login_time) + '}')
return data
def do_GET(self):
if self.path == '/':
self.path = './src/html/index.html'
elif self.path == '/login':
self.path = './src/html/Login.html'
elif self.path == '/signup':
self.path = './src/html/Signup.html'
elif self.path == '/forgotpwd':
self.path = './src/html/ForgotPwd.html'
elif self.path == '/home' and islogin == True:
self.path = './src/html/singnedIn.html'
try:
split_path = os.path.splitext(self.path)
request_extension = split_path[1]
if request_extension != ".py":
f = read_html_template(self.path)
self.send_response(200)
self.end_headers()
self.wfile.write(bytes(f, 'utf-8'))
else:
f = "File not found"
self.send_error(404,f)
except:
f = "File not found"
self.send_error(404,f)
with HTTPServer(('', 8000), handler) as server:
server.serve_forever()
My idea is write data to a json file and send it to client but 2 things I don't know is
How to send json file ? and
How to get data and write it to json file ?

Related

multi threading http server in python

I am trying to build a HTTP server in python,
that sniffs packets and sends them to an other interface.
the server can get routing paths through a POST http request.
So that I need that the server will parallely sniff pakets and listen to http requests.
this is my code:
from scapy.all import *
from scapy.layers.inet import IP, UDP
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
from socketserver import ThreadingMixIn
import threading
ROUTING_LIST = []
INTERFACE_TO_SNIFF = 'vEthernet'
PORT = 80
class Route:
def __init__(self):
self.first_IP_src = ""
self.first_port_src = ""
self.first_IP_dst = ""
self.first_port_dst = ""
self.first_iface = ""
self.second_IP_src = ""
self.second_port_src = ""
self.second_IP_dst = ""
self.second_port_dst = ""
self.second_iface = ""
class Server(BaseHTTPRequestHandler):
# POST echoes the message adding a JSON field
def do_POST(self):
# read the message and convert it into a python dictionary
length = int(self.headers['Content-length'])
message = self.rfile.read(length)
routing_dict = json.loads(message, strict=False)
if add_routing_http(routing_dict) is True:
print("New Routing received:")
print("{" + "\n".join("{!r}: {!r},".format(k, v) for k, v in routing_dict.items()) + "}")
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(
("POST routing request received! now we have " + str(len(ROUTING_LIST)) + " routes").encode("utf8"))
def run_server():
global PORT
server_address = ('', PORT)
httpd = HTTPServer(server_address, Server)
print('Starting httpd on port %d...' % PORT)
httpd.serve_forever()
def add_routing_local(first_IP_src, first_port_src, first_IP_dst, first_port_dst, first_iface,
second_IP_src, second_port_src, second_IP_dst, second_port_dst, second_iface):
global ROUTING_LIST
temp = Route()
temp.first_IP_src = first_IP_src
temp.first_port_src = first_port_src
temp.first_IP_dst = first_IP_dst
temp.first_port_dst = first_port_dst
temp.first_iface = first_iface
temp.second_IP_src = second_IP_src
temp.second_port_src = second_port_src
temp.second_IP_dst = second_IP_dst
temp.second_port_dst = second_port_dst
temp.second_iface = second_iface
ROUTING_LIST.append(temp)
def add_routing_http(routing_dict):
global ROUTING_LIST
temp = Route()
temp.first_IP_src = routing_dict.get('firstIpSrc')
temp.first_port_src = routing_dict.get('firstPortSrc')
temp.first_IP_dst = routing_dict.get('firstIpDst')
temp.first_port_dst = routing_dict.get('firstPortDst')
temp.first_iface = routing_dict.get('firstIface')
temp.second_IP_src = routing_dict.get('secondIpSrc')
temp.second_port_src = routing_dict.get('secondPortSrc')
temp.second_IP_dst = routing_dict.get('secondIpDst')
temp.second_port_dst = routing_dict.get('secondPortDst')
temp.second_iface = routing_dict.get('secondIface')
ROUTING_LIST.append(temp)
return True
def packets_filter(packet):
return IP in packet and UDP in packet and Raw in packet
def match_packet(packet, routing):
match = True
if routing.first_IP_src != '' and packet[IP].src != routing.first_IP_src:
return False
if routing.first_IP_dst != '' and packet[IP].dst != routing.first_IP_dst:
return False
if routing.first_port_src != '' and packet[UDP].sport != routing.first_port_src:
return False
if routing.first_port_dst != '' and packet[UDP].dport != routing.first_port_dst:
return False
if routing.first_iface != '' and packet.sniffed_on is not None and routing.first_iface != packet.sniffed_on:
return False
return True
def handle_packet(packet):
global ROUTING_LIST
for routing in ROUTING_LIST:
if match_packet(packet, routing) is True:
new_packet = packet.copy()
new_packet[IP].src = routing.second_IP_src
new_packet[IP].dst = routing.second_IP_dst
new_packet[UDP].sport = routing.second_port_src
new_packet[UDP].dport = routing.second_port_dst
new_packet.show()
sendp(new_packet) # sendp(new_packet, iface=routing.second_iface)iface='eth0'
return
def main():
daemon = threading.Thread(name='daemon_server', target=run_server, args=())
daemon.setDaemon(True) # Set as a daemon so it will be killed once the main thread is dead.
daemon.start()
print("start sniffing")
sniff(lfilter=packets_filter, prn=handle_packet) # sniff(lfilter=packets_filter, prn=handle_packet, iface=INTERFACE_TO_SNIFF)
if __name__ == "__main__":
main()
In short - I wantthe main function to run in parallel both of functions: run_server, sniff. if I try to run inly one of them - both work great.
In this code only the run_server works but not the sniffing.
What is wrong?
thank you
You have created Thread only for the run_server method. In order to run the sniff function on multithreaded, you will have to create a thread for the sniff function too.
You can learn about basic multithreading from this document:
https://www.geeksforgeeks.org/multithreading-python-set-1/

Can't get python exe to run

So i'm having issues getting my python 3.5 script to run as an exe. Here is the code I am using:
import base64
import imaplib
import json
import smtplib
import urllib.parse
import urllib.request
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import lxml.html
GOOGLE_ACCOUNTS_BASE_URL = 'https://accounts.google.com'
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
GOOGLE_CLIENT_ID = '<FILL ME IN>'
GOOGLE_CLIENT_SECRET = '<FILL ME IN>'
GOOGLE_REFRESH_TOKEN = None
def command_to_url(command):
return '%s/%s' % (GOOGLE_ACCOUNTS_BASE_URL, command)
def url_escape(text):
return urllib.parse.quote(text, safe='~-._')
def url_unescape(text):
return urllib.parse.unquote(text)
def url_format_params(params):
param_fragments = []
for param in sorted(params.items(), key=lambda x: x[0]):
param_fragments.append('%s=%s' % (param[0], url_escape(param[1])))
return '&'.join(param_fragments)
def generate_permission_url(client_id, scope='https://mail.google.com/'):
params = {}
params['client_id'] = client_id
params['redirect_uri'] = REDIRECT_URI
params['scope'] = scope
params['response_type'] = 'code'
return '%s?%s' % (command_to_url('o/oauth2/auth'), url_format_params(params))
def call_authorize_tokens(client_id, client_secret, authorization_code):
params = {}
params['client_id'] = client_id
params['client_secret'] = client_secret
params['code'] = authorization_code
params['redirect_uri'] = REDIRECT_URI
params['grant_type'] = 'authorization_code'
request_url = command_to_url('o/oauth2/token')
response = urllib.request.urlopen(request_url, urllib.parse.urlencode(params).encode('UTF-8')).read().decode('UTF-8')
return json.loads(response)
def call_refresh_token(client_id, client_secret, refresh_token):
params = {}
params['client_id'] = client_id
params['client_secret'] = client_secret
params['refresh_token'] = refresh_token
params['grant_type'] = 'refresh_token'
request_url = command_to_url('o/oauth2/token')
response = urllib.request.urlopen(request_url, urllib.parse.urlencode(params).encode('UTF-8')).read().decode('UTF-8')
return json.loads(response)
def generate_oauth2_string(username, access_token, as_base64=False):
auth_string = 'user=%s\1auth=Bearer %s\1\1' % (username, access_token)
if as_base64:
auth_string = base64.b64encode(auth_string.encode('ascii')).decode('ascii')
return auth_string
def test_imap(user, auth_string):
imap_conn = imaplib.IMAP4_SSL('imap.gmail.com')
imap_conn.debug = 4
imap_conn.authenticate('XOAUTH2', lambda x: auth_string)
imap_conn.select('INBOX')
def test_smpt(user, base64_auth_string):
smtp_conn = smtplib.SMTP('smtp.gmail.com', 587)
smtp_conn.set_debuglevel(True)
smtp_conn.ehlo('test')
smtp_conn.starttls()
smtp_conn.docmd('AUTH', 'XOAUTH2 ' + base64_auth_string)
def get_authorization(google_client_id, google_client_secret):
scope = "https://mail.google.com/"
print('Navigate to the following URL to auth:', generate_permission_url(google_client_id, scope))
authorization_code = input('Enter verification code: ')
response = call_authorize_tokens(google_client_id, google_client_secret, authorization_code)
return response['refresh_token'], response['access_token'], response['expires_in']
def refresh_authorization(google_client_id, google_client_secret, refresh_token):
response = call_refresh_token(google_client_id, google_client_secret, refresh_token)
return response['access_token'], response['expires_in']
def send_mail(fromaddr, toaddr, subject, message):
access_token, expires_in = refresh_authorization(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REFRESH_TOKEN)
auth_string = generate_oauth2_string(fromaddr, access_token, as_base64=True)
msg = MIMEMultipart('related')
msg['Subject'] = subject
msg['From'] = fromaddr
msg['To'] = toaddr
msg.preamble = 'This is a multi-part message in MIME format.'
msg_alternative = MIMEMultipart('alternative')
msg.attach(msg_alternative)
part_text = MIMEText(lxml.html.fromstring(message).text_content().encode('utf-8'), 'plain', _charset='utf-8')
part_html = MIMEText(message.encode('utf-8'), 'html', _charset='utf-8')
msg_alternative.attach(part_text)
msg_alternative.attach(part_html)
server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo(GOOGLE_CLIENT_ID)
server.starttls()
server.docmd('AUTH', 'XOAUTH2 ' + auth_string)
server.sendmail(fromaddr, toaddr, msg.as_string())
server.quit()
def main():
if GOOGLE_REFRESH_TOKEN is None:
print('No refresh token found, obtaining one')
refresh_token, access_token, expires_in = get_authorization(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET)
print('Set the following as your GOOGLE_REFRESH_TOKEN:', refresh_token)
exit()
send_mail('--------#gmail.com', '--------#gmail.com',
'A mail from you from Python',
'<b>A mail from you from Python</b><br><br>' +
'So happy to hear from you!')
input("Success!")
print(__name__)
input("Wait!!")
if __name__ == '__main__':
main()
When i run the code in pyCharm is works great, when i use pyinstaller it creates the exe. When i run the EXE it will open a new cmd prmpt with no text in it, then it closes. Any ideas why it doesn't print the name or "Wait!!" on the screen?
I named the file main and it works great in PyCharm.
I'm not familiar with troubleshooting code that works in an IDE and does nothing as an exe. Is there a basic troubleshooting guide for that?
Most of the problems are errors caused by imported modules.
Here are two ways I think of
Use exception handling and use traceback.format_exc() to display the contents when an error occurs.
Errors are usually associated with the sys.stderr, so you can redirect stderr output a specified format to a specified file or the like.
Example:
import sys
from pathlib import Path
from os import startfile
import traceback
DEBUG = True
class CaptureStderr:
__slots__ = ('debug_flag',
'original',
'log',)
def __init__(self, debug_flag=False, log=None):
self.debug_flag = debug_flag
self.original = sys.stderr # Keep track of original
self.log = log
def new_log_file(self, log_path: Path = Path('temp.log').resolve()):
self.log = open(str(log_path), 'w')
return self.log
def start(self):
""" Start filtering and redirecting stderr """
sys.stderr = self
def stop(self):
""" Stop filtering and redirecting stderr """
sys.stderr = self.original
def write(self, message: str):
""" When sys.stderr.write is called, it will re directed here"""
if not self.debug_flag:
self.original.write(message)
self.original.flush()
return
if self.log:
self.log.write(message)
def main():
...
if __name__ == '__main__':
try: # method 1
from .notexistmodule import notexistclass
# Put modules that you are not sure whether it is 100% import successful on here.
main()
except:
print(traceback.format_exc())
# method 2: redirect sys.stderr
cs = CaptureStderr(DEBUG)
cs.new_log_file(Path('error.log'))
cs.start()
from .notexistmodule2 import notexistclass2
main()
cs.stop()
startfile(cs.log.name)
You probably have an error in the exe, most likely an import error.
Run your exe like this to see the error:
Create a .bat file to run the exe with the following commands
start C:\Path\To\.exe
pause
This will stop the command prompt from exiting until you press a key on the keyboard, letting you read the output.

python http server threading via cli

New in version 3.7 supports ThreadingHTTPServer as mentioned in doc
to run from command line we use
python -m http.server
but its still run normal HTTPServer, is there any way to enable via command line.
EDITED:
python 3.7 runs ThreadingHTTPServer by default, no argument necessary
Simple Python 2 HTTP Server with multi-threading and partial-content support
#!/usr/bin/env python2
# Standard library imports.
from SocketServer import ThreadingMixIn
import BaseHTTPServer
import SimpleHTTPServer
import sys
import json
import os
from os.path import (join, exists, dirname, abspath, isabs, sep, walk, splitext,
isdir, basename, expanduser, split, splitdrive)
from os import makedirs, unlink, getcwd, chdir, curdir, pardir, rename, fstat
from shutil import copyfileobj, copytree
import glob
from zipfile import ZipFile
from urlparse import urlparse, parse_qs
from urllib import urlopen, quote, unquote
from posixpath import normpath
from cStringIO import StringIO
import re
import ConfigParser
import cgi
import threading
import socket
import errno
DATA_DIR = getcwd() # join(expanduser('~'), APP_NAME)
class ThreadingHTTPServer(ThreadingMixIn, BaseHTTPServer.HTTPServer):
pass
class RequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
""" Handler to handle POST requests for actions.
"""
serve_path = DATA_DIR
def do_GET(self):
""" Overridden to handle HTTP Range requests. """
self.range_from, self.range_to = self._get_range_header()
if self.range_from is None:
# nothing to do here
return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
print 'range request', self.range_from, self.range_to
f = self.send_range_head()
if f:
self.copy_file_range(f, self.wfile)
f.close()
def copy_file_range(self, in_file, out_file):
""" Copy only the range in self.range_from/to. """
in_file.seek(self.range_from)
# Add 1 because the range is inclusive
bytes_to_copy = 1 + self.range_to - self.range_from
buf_length = 64*1024
bytes_copied = 0
while bytes_copied < bytes_to_copy:
read_buf = in_file.read(min(buf_length, bytes_to_copy-bytes_copied))
if len(read_buf) == 0:
break
out_file.write(read_buf)
bytes_copied += len(read_buf)
return bytes_copied
def send_range_head(self):
"""Common code for GET and HEAD commands.
This sends the response code and MIME headers.
Return value is either a file object (which has to be copied
to the outputfile by the caller unless the command was HEAD,
and must be closed by the caller under all circumstances), or
None, in which case the caller has nothing further to do.
"""
path = self.translate_path(self.path)
f = None
if isdir(path):
if not self.path.endswith('/'):
# redirect browser - doing basically what apache does
self.send_response(301)
self.send_header("Location", self.path + "/")
self.end_headers()
return None
for index in "index.html", "index.htm":
index = join(path, index)
if exists(index):
path = index
break
else:
return self.list_directory(path)
if not exists(path) and path.endswith('/data'):
# FIXME: Handle grits-like query with /data appended to path
# stupid grits
if exists(path[:-5]):
path = path[:-5]
ctype = self.guess_type(path)
try:
# Always read in binary mode. Opening files in text mode may cause
# newline translations, making the actual size of the content
# transmitted *less* than the content-length!
f = open(path, 'rb')
except IOError:
self.send_error(404, "File not found")
return None
if self.range_from is None:
self.send_response(200)
else:
self.send_response(206)
self.send_header("Content-type", ctype)
fs = fstat(f.fileno())
file_size = fs.st_size
if self.range_from is not None:
if self.range_to is None or self.range_to >= file_size:
self.range_to = file_size-1
self.send_header("Content-Range",
"bytes %d-%d/%d" % (self.range_from,
self.range_to,
file_size))
# Add 1 because ranges are inclusive
self.send_header("Content-Length",
(1 + self.range_to - self.range_from))
else:
self.send_header("Content-Length", str(file_size))
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.end_headers()
return f
def list_directory(self, path):
"""Helper to produce a directory listing (absent index.html).
Return value is either a file object, or None (indicating an
error). In either case, the headers are sent, making the
interface the same as for send_head().
"""
try:
list = os.listdir(path)
except os.error:
self.send_error(404, "No permission to list directory")
return None
list.sort(key=lambda a: a.lower())
f = StringIO()
displaypath = cgi.escape(unquote(self.path))
f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
f.write("<hr>\n<ul>\n")
for name in list:
fullname = os.path.join(path, name)
displayname = linkname = name
# Append / for directories or # for symbolic links
if os.path.isdir(fullname):
displayname = name + "/"
linkname = name + "/"
if os.path.islink(fullname):
displayname = name + "#"
# Note: a link to a directory displays with # and links with /
f.write('<li>%s\n'
% (quote(linkname), cgi.escape(displayname)))
f.write("</ul>\n<hr>\n</body>\n</html>\n")
length = f.tell()
f.seek(0)
self.send_response(200)
encoding = sys.getfilesystemencoding()
self.send_header("Content-type", "text/html; charset=%s" % encoding)
self.send_header("Content-Length", str(length))
self.end_headers()
return f
def translate_path(self, path):
""" Override to handle redirects.
"""
path = path.split('?',1)[0]
path = path.split('#',1)[0]
path = normpath(unquote(path))
words = path.split('/')
words = filter(None, words)
path = self.serve_path
for word in words:
drive, word = splitdrive(word)
head, word = split(word)
if word in (curdir, pardir): continue
path = join(path, word)
return path
# Private interface ######################################################
def _get_range_header(self):
""" Returns request Range start and end if specified.
If Range header is not specified returns (None, None)
"""
range_header = self.headers.getheader("Range")
if range_header is None:
return (None, None)
if not range_header.startswith("bytes="):
print "Not implemented: parsing header Range: %s" % range_header
return (None, None)
regex = re.compile(r"^bytes=(\d+)\-(\d+)?")
rangething = regex.search(range_header)
if rangething:
from_val = int(rangething.group(1))
if rangething.group(2) is not None:
return (from_val, int(rangething.group(2)))
else:
return (from_val, None)
else:
print 'CANNOT PARSE RANGE HEADER:', range_header
return (None, None)
def get_server(port=8000, next_attempts=0, serve_path=None):
Handler = RequestHandler
if serve_path:
Handler.serve_path = serve_path
while next_attempts >= 0:
try:
httpd = ThreadingHTTPServer(("", port), Handler)
return httpd
except socket.error as e:
if e.errno == errno.EADDRINUSE:
next_attempts -= 1
port += 1
else:
raise
def main(args=None):
if args is None:
args = sys.argv[1:]
PORT = 8000
if len(args)>0:
PORT = int(args[-1])
serve_path = DATA_DIR
if len(args) > 1:
serve_path = abspath(args[-2])
httpd = get_server(port=PORT, serve_path=serve_path)
print "serving at port", PORT
httpd.serve_forever()
if __name__ == "__main__" :
main()

http.server if statement os.path.isfile() doesn't work

So this is my code:
from http.server import BaseHTTPRequestHandler, HTTPServer
import requests, json, os
PORT = 1337
class getHandler(BaseHTTPRequestHandler):
def handleJSON(self, provider, data):
if provider == "provider_1":
json_data = json.loads(data)
sl_token = json_data["access_token"]
return sl_token
elif provider == "provider_2":
json_data = json.loads(data)
pb_token = json_data["access_token"]
return pb_token
def do_GET(self):
data = self.requestline
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write(b'You may close the tab now')
print("Raw Data: " + data)
if not os.path.isfile("PbToken.txt") and os.path.isfile("SlToken.txt"):
if "GET /?code=" and "&state=" in data: # Provider_1
print("Provider_1 Data:", data)
pb_code = data[data.find("/?code=") + len("/?code="):data.find("&state=")]
with open("PbToken.txt", "w") as file:
file.write(pb_code)
file.close()
elif "GET /?code=" in data: # Provider_2
print("Provider_2 Data:", data)
sl_code = data.strip()
sl_code = sl_code[sl_code.rindex("/?code=") + len("/?code="):sl_code.rindex(" ")]
with open("SlToken.txt", "w") as file:
file.write(sl_code)
file.close()
else:
raise SystemExit
server = HTTPServer(('localhost', PORT), getHandler)
print("Started server on port", PORT)
server.serve_forever()
So from the class getHandler in the function do_GET(self) it never makes it past the if not os.path.isfile("PbToken.txt") and os.path.isfile("SlToken.txt"): statement (I've of course made sure the files aren't actually there). I want it to check if both of the files exist, if they don't do what's written below. If the files exist they should go straight to the else statement where it uses raise SystemExit. What am I doing wrong?
It should've been or not and...
So simply if not os.path.isfile("PbToken.txt") or not os.path.isfile("SlToken.txt"): to see if one of the files are missing.

cherrypy didn't work correctly whith daemonize

I'm new in cherrypy, and I try to develop a small application by using this framework. My problem is, this application can serves well and browser can access when cherrypy works in undaemonizer mode. But when I write code by using cherrypy.process.plugins.Daemonizer(), cherrypy started in background, and it listen on specific port, but browser will get a connection refused( iptables or ufw already shutted down but still inaccessible ). The incredible thing is, when I start it with daemoned mode, I can still start a undaemoned process , and they listen on the same port. I wonder why would this happend, and how to solve it?
Simply saids: With Daemonizer starts, cherrypy listened on specified port, but browser connection refused; without Daemonizer, cherrypy works very well.
Thanks alot
with my code
from optparse import OptionParser
from cherrypy.process.plugins import Daemonizer
from cherrypy.process.plugins import PIDFile
import cherrypy
import json
import urllib
import datetime
try:
import cPickle as pickle
except:
import pickle
import time
import base64
import os
import sys
'''
cherrypy class
'''
class Index(object):
#cherrypy.expose
def index(self):
return "Say hello to the yellow elephant"
class System(object):
#cherrypy.expose
def env(self, token):
local_token = Token()
if local_token.AuthToken(token) is True:
env = get_env()
return json.dumps(env)
return '{"errcode", "Invalid token"}'
class Jmx(object):
#cherrypy.expose
def get(self, token, host, port, qry):
local_token = Token()
if local_token.AuthToken(token) is True:
url = 'http://' + host + ':' + port + '/jmx?qry=' + qry
jmx = urllib.urlopen(url)
jmx_data = jmx.read().replace('\n', '')
jmx.close()
return jmx_data
return '{"errcode", "Invalid token"}'
"""
command uses base64 encode by using http post method
"""
class Command(object):
def __init__(self):
self.fname = datetime.datetime.now().strftime('%Y-%m-%d_%M-%M-%S') + '.log'
#cherrypy.expose
def run(self, token, command):
local_token = Token()
command = base64.b64decode(command)
if local_token.AuthToken(token) is True:
os.popen(command + ' 2>&1 > /usr/lib/agent/output/' + self.fname)
return '{"errcode", "Invalid token"}'
#cherrypy.expose
def readlog(self, token):
local_token = Token()
if local_token.AuthToken(token) is True:
log = open('/usr/lib/agent/output/' + self.fname)
lines = log.readlines()
log.close()
return json.dumps(lines, ensure_ascii=False)
return '{"errcode", "Invalid token"}'
"""
First time access from central, it will create a new token on slave node, the token is pickle.dump(cacl_mysql_passwd(conf['agent']['secret']))
By token created , if central makes change to secret, the slave node will be inaccessible!!!
"""
class Token(object):
def AuthToken(self, token):
if(os.path.isfile('/usr/lib/agent/key/authenticate.key')) is False:
return self.CreateToken(token)
else:
try:
k = open('/usr/lib/agent/key/authenticate.key', 'rb')
tokenizer = pickle.load(k)
k.close()
if token == tokenizer:
return True
else:
return False
except IOError, e:
return '{"errcode":"' + str(e).replace('\n', '<br/>') + '"}'
#cherrypy.expose
def CreateToken(self, token):
if(os.path.isfile('/usr/lib/agent/key/authenticate.key')) is False:
try:
k = open('/usr/lib/agent/key/authenticate.key', 'wb')
pickle.dump(token, k)
k.close()
return True
except IOError, e:
return '{"Exception":"' + str(e).replace('\n', '<br/>') + '"}'
else:
return '{"errcode":"token exists"}'
class Controller:
def __init__(self, pidfile='/var/run/agent/agent.pid', host='0.0.0.0', port=30050):
self.port = port
self.host = host
self.pidfile = pidfile
self.settings = {
'global': {
'server.socket_port': port,
'server.socket_host': host,
'server.socket_file': '',
'server.socket_queue_size': 5,
'server.protocol_version': 'HTTP/1.1',
'server.log_to_screen': True,
'server.log_file': '',
'server.reverse_dns': False,
'server.thread_pool': 10,
'server.environment': 'production',
'engine.timeout_monitor.on': False
}
}
def start(self):
if os.path.exists(self.pidfile):
sys.stderr.write('PID file exists, server running?\n')
sys.exit(1)
else:
Daemonizer(cherrypy.engine, stdin='/dev/stdin', stdout='/dev/stdout', stderr='/dev/stderr').subscribe()
PIDFile(cherrypy.engine, self.pidfile).subscribe()
cherrypy.tree.mount(Index(), '/')
cherrypy.tree.mount(System(), '/system')
cherrypy.tree.mount(Command(), '/command')
cherrypy.tree.mount(Jmx(), '/jmx')
cherrypy.config.update(self.settings)
cherrypy.engine.start()
cherrypy.engine.block()
def stop(self):
cherrypy.config.update(self.settings)
if os.path.exists(self.pidfile):
cherrypy.engine.stop()
cherrypy.engine.exit()
try:
process = open(self.pidfile).read().strip()
if process != 0:
os.popen('kill -9 %s' % process)
os.remove(self.pidfile)
except IOError, e:
sys.stderr.write(str(e))
else:
sys.stderr.write('PID file does not exist, server gone?\n')
sys.exit(1)
if '__main__' == __name__:
cherrypy.engine.autoreload.stop()
cherrypy.engine.autoreload.unsubscribe()
syntax = 'Syntax: %prog -b 192.168.1.1 -s start'
parser = OptionParser(usage=syntax)
ip = os.popen('hostname -i').read().strip()
hostname = os.popen('hostname --fqdn').read().strip()
parser.add_option('-b', '--bind', action='store', type='string', dest='bind', default=ip, help='Inner network IP address, default value is hostname -i')
parser.add_option('-s', '--signal', action='store', type='string', dest='signal', help='Valid signal is {start|stop|restart}')
options, args = parser.parse_args()
if len(sys.argv) == 1:
print 'Use %s -h or --help for help.' % sys.argv[0]
else:
if options.signal == '':
print 'Must give -s option\'s value'
else:
daemon = Controller(pidfile='/var/run/agent/agent.pid', host=options.bind)
if 'start' == options.signal:
daemon.start()
elif 'stop' == options.signal:
daemon.stop()
else:
print 'Invalid signal'
sys.exit(1)

Categories