#!/usr/bin/env python
#-*-Coding:utf-8-*-
# @CreateTime : 2018/5/29
# @Author : 593703
# @File : server_client.py
# @Software : SC
# @since : 0.0.1
# @Desc : Socket server and Client
# @license : Copyright (c) 2018, Inc. All rights reserved.
# @Contact : [Email protected]
Import OS
Import Sys
Sys.path.append (Os.path.join (Os.path.dirname (Os.path.abspath (__file__)), Os.path.pardir))
Import Asyncore
Import subprocess
Import socket
Import struct
Import errno
From Sfo_common.import_common Import *
From agent.agent Import *
From threading Import Event
#配置和日志部分, modify according to your needs
Config = config ()
Logging.config.fileConfig (config.logging_conf)
Logger = Logging.getlogger ("server")
Util = Util ()
EVT = Event ()
Class Util (object):
def __init__ (self):
Pass
def ensure_dir (self, pathname):
DirName = os.path.dirname (pathname)
If not os.path.exists (dirname):
Os.makedirs (dirname)
def excute_command (self, CMDSTR):
Try
Process = subprocess. Popen (Cmdstr, stdout=subprocess. PIPE, Shell=true)
stdout, stderr = Process.communicate ()
If Process.returncode = = 0:
If Len (stdout) = = 0:
Return ' SUCCESS '
Return str (STDOUT). Strip ()
elif Process.returncode = = 1:
If StdOut is None:
Return ' Operation not permitted '
Else
return stdout
Else
Print "RC:%s"% Process.returncode
Print stdout
Raise Exception ("stderr:%s"% str (stderr))
Except Exception as ex:
Logger.info ("Excute_command function Excute Exception:" + str (ex))
def exct_cmd (self, CMDSTR):
Process = subprocess. Popen (Cmdstr, stdout=subprocess. PIPE, Shell=true,stderr=subprocess. STDOUT)
res = Process.stdout.readlines ()
Process.stdout.flush ()
Process.stdout.close ()
return res
Class Clustercommandhandler (Asyncore.dispatcher_with_send):
def handle_read (self):
data = SELF.RECV (1024)
Self.out_buffer + = Data
def writable (self):
Return (len (Self.out_buffer) > 0)
def handle_write (self):
res = {}
If Len (Self.out_buffer) > 0:
If Len (self.out_buffer) > 1024:
Excute_cmd = ' '
While Len (Self.out_buffer) > 0:
CMDSTR = self.out_buffer[:1024]
If Util.is_json (CMDSTR):
param = Json.loads (cmdstr, encoding= ' Utf-8 ')
Excute_cmd + = param[' cmd ']
Self.out_buffer = self.out_buffer[1024:]
result = Util.excute_command (excute_cmd)
If Len (Result) > 512:
While 1:
REC = result[:512]
result = result[512:]
If not result:
If Len (rec) > 0:
Self.send (bytes (rec))
Logger.info (REC)
Break
Self.send (bytes (rec))
Logger.info (REC)
Else
REC = result[:512]
Self.send (bytes (rec))
Logger.info (REC)
Else
If Util.is_json (self.out_buffer):
Bsize = Len (self.out_buffer)
param = Json.loads (self.out_buffer, encoding= ' Utf-8 ')
Self.out_buffer = self.out_buffer[bsize:]
If Param.has_key (' cmd '):
result = Util.excute_command (param[' cmd ')
If Len (Result) > 512:
While 1:
REC = result[:512]
result = result[512:]
If not result:
If Len (rec) > 0:
Self.send (bytes (rec))
Logger.info (REC)
Break
Self.send (bytes (rec))
Logger.info (REC)
Else
REC = result[:512]
Self.send (bytes (rec))
Logger.info (REC)
Else
Self.send (' Error params ')
Logger.info (' Error params ')
# server that handles commands
Class Clustercommandserver (Asyncore.dispatcher):
def __init__ (self):
Asyncore.dispatcher.__init__ (self)
Self.create_socket (socket.af_inet, socket. SOCK_STREAM)
SELF.SET_REUSE_ADDR ()
Host = Socket.gethostname ()
Port = Config.sock_cmd_port
Self.bind ((host, Port))
Self.listen (5)
def handle_accept (self):
Pair = Self.accept ()
If pair is not None:
conn, addr = Pair
Logger.info (' Incoming connection from%s '% repr (addr))
Handler = Clustercommandhandler (conn)
Class Clusterfilehandler (Asyncore.dispatcher_with_send):
def handle_read (self):
While 1:
Fileinfo_size = struct.calcsize (' >128SL ')
BUF = Self.recv (fileinfo_size)
If BUF:
FileName, filesize = struct.unpack (' >128SL ', buf)
fn = Filename.strip (' \00 ')
Util.ensure_dir (Config.temp_file)
New_filename = Os.path.join (Config.temp_file, FN)
If Os.path.exists (new_filename):
Os.remove (New_filename)
Logger.info (' File New name is ' {0} ' filesize ' {1} Bytes '. Format (New_filename, filesize))
recvd_size = 0 # Defines the size of the received file
fp = open (New_filename, ' WB ')
While not recvd_size = = FileSize:
Try
If Filesize-recvd_size > 1024:
data = SELF.RECV (1024)
Recvd_size + = len (data)
Else
data = SELF.RECV (filesize-recvd_size)
Recvd_size = FileSize
Except Ioerror,error:
if Error.errno = = errno. Ewouldblock:
Pass
Else
Fp.write (data)
Fp.close ()
Self.out_buffer = fn
Break
def handle_write (self):
Try
res = {}
If Len (Self.out_buffer) > 0:
res[' file ' = Self.out_buffer
Self.out_buffer = ' '
res[' status '] = ' OK '
res[' result ' = ' File receive Compeled '
REC = json.dumps (res, encoding= ' Utf-8 ', ensure_ascii=true)
Self.send (REC)
Logger.info (REC)
Except Socket.error as E:
Raise E
# server that handles transferring files
Class Clusterfileserver (Asyncore.dispatcher):
def __init__ (self):
Asyncore.dispatcher.__init__ (self)
Self.create_socket (socket.af_inet, socket. SOCK_STREAM)
SELF.SET_REUSE_ADDR ()
Host = Socket.gethostname ()
Port = Config.sock_file_port
Self.bind ((host, Port))
Self.listen (5)
def handle_accept (self):
Pair = Self.accept ()
If pair is not None:
conn, addr = Pair
Logger.info (' Incoming connection from%s '% repr (addr))
Handler = Clusterfilehandler (conn)
Class Clusterclient (Asyncore.dispatcher):
def __init__ (self, host= ' 127.0.0.1 ', port=9999, Message=none, Filepath=none):
Asyncore.dispatcher.__init__ (self)
Self.create_socket (socket.af_inet, socket. SOCK_STREAM)
Self.host = Host
Self.port = Port
Self.message = Message
Self.filepath = FilePath
Self.buffer = ' __wait__ '
Self.content = ' '
Self.connect ((Self.host, Self.port))
def handle_connect (self):
Pass
def handle_close (self):
Self.close ()
def handle_read (self):
data = SELF.RECV (512)
If Len (data) > 0 and Len (data) < 512:
Self.buffer + = Data
Self.handle_close ()
Else
Self.buffer + = Data
def writable (self):
Return (len (Self.buffer) > 0)
def handle_write (self):
# Execute Command
If Self.message is not None:
Cmds = {}
Sent_size = 1014 # The JSON is added with 10 characters after stitching
If Len (self.message[:sent_size]) > 0:
cmds[' cmd '] = self.message[:sent_size]
Cmdstr = Json.dumps (Cmds, encoding= ' Utf-8 ', ensure_ascii=true)
Sent = Self.send (CMDSTR)
Self.message = self.message[sent_size:]
# Make sure writable is true
Self.buffer = self.message[sent_size:]
# Transferring files
If Self.filepath is not None:
While True:
If Os.path.isfile (Self.filepath):
# define the definition file information. 128s means the file name is 128bytes long, l represents an int or log file type, where file size, plus ">" symbol is to resolve Windows Linux inter-pass exception
Fileinfo_size = struct.calcsize (' >128SL ')
# defines header information, including file name and file size
Fhead = Struct.pack (' >128sl ', Os.path.basename (Self.filepath),
Os.stat (Self.filepath). St_size)
Self.send (Fhead)
Logger.info (' client filepath: {0} '. Format (Self.filepath))
With open (Self.filepath, ' RB ') as FP:
While 1:
data = Fp.read (1024)
If not data:
Logger.info (' {0} file send over ... '. Format (Self.filepath))
Self.filepath = None
Self.buffer = ' '
Break
Self.send (data)
Break
If Self.buffer is not None:
if Self.buffer = = ' __wait__ ':
Self.buffer = ' '
Else
Pass
def handler (Signum, frame):
Logger.info ("Signal handler called with Signal, {}. Set the internal flag to true for Event. Format (Signum))
Evt.set ()
#agent参考上一篇agent编写, this is just part of the implementation.
Class ServerAgent (Agent):
def __init__ (self, pidfile):
Agent.__init__ (self, pidfile)
def run (self):
Server1 = Clustercommandserver ()
Server2 = Clusterfileserver ()
Asyncore.loop ()
Signal.signal (signal. SIGTERM, Handler)
While not Evt.isset ():
Evt.wait (600)
Logger.info ("ServerAgent stoped")
if __name__ = = ' __main__ ':
#配置文件路径修改为自己的文件路径
Agent = ServerAgent (config.server_agnet_pfile)
Try
If Len (sys.argv) = = 3:
If ' server ' = = Sys.argv[1]:
If ' start ' = = Sys.argv[2]:
Agent.start ()
If ' stop ' = = Sys.argv[2]:
Agent.stop ()
Elif ' client ' = = Sys.argv[1]:
If ' start ' = = Sys.argv[2]:
#client = clusterclient (host= ' 10.202.127.4 ', port=7201, message= ' systemctl start Openstack-swift-container-auditor ')
Client = clusterclient (host= ' 10.202.127.4 ', port=7202, filepath= '/tmp/123/1.txt ')
Asyncore.loop ()
Print Client.buffer
Else
Print ("Unknown command")
Sys.exit (2)
Else
Print ("Usage:%s"% (Sys.argv[0],))
Sys.exit (2)
Except Exception as ex:
Logger.info ("Cluster Server client Run exception:" + str (ex))
Python uses Asyncore to implement the socket server client